Opération sur châine de caractère avec balises HTML

Mammouth du PHP | 531 Messages

22 avr. 2008, 00:12

Bonjour,

Je cherche à faire un petit travail sur les chaines de caractères mais je ne sais pas trop comment m'y prendre.

Par exemple, sur cette chaine $x, qui pourrais très bien être différente. L'important et qu'elle sera toujours composé d'un ou plusieurs paragraphes :

<p>Et cette fois, voilà une description</p>
<p>Plus longue et avec 2 paragraphe.</p>


Je voudrais simplement arriver au résultat suivant :

Ne récupérer que le premier paragraphe de la chaine, dans tous les cas. Qu'il y en ait 1, 2 ou 5... Donc dès que je rencontre la première balise de fermeture </p>, stopper. Je ne sais tout simplement pas comment faire... eregi() à elle seule ne suffit pas, il faut surement combiner cette fonction à une autre ?

:?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

22 avr. 2008, 08:21

Penche toi du côté des expressions régulière et de preg_match(). Ton masque est assez simple à réaliser, tu ne devrais pas avoir trop de difficulter à capturer le contenu du premier paragraphe :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 531 Messages

22 avr. 2008, 11:28

En théorie je ferrais comme ça, mais si dans ma chaine il y a 2 balises de fermetures, comment ça se passe ? Il faudrait que l'analyse de la chiane se termine dès lors qu'une balise est trouvée.
<?php
$chaine = '<p>blabla</p><p>Titi</p>';
if ( preg_match( '</p>',  $chaine ) ) {
    // Etape 2 : Récupérer la position en cours qui correspond à l'emplacement de </p>
} else {
    echo "Aucun résultat.";
}
?> 

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

22 avr. 2008, 12:06

Il te manque la notion de capture dans ton expression (et un délimiteur d'expression régulière). Il te faut utiliser des parenthèse pour "capturer" la partie de la chaine qui t'intéresse, et une variable pour récupérer les valeurs capturées :
if ( preg_match( '#(.*)</p>#i',  $chaine, $matches ) ) { 
  echo '<pre>';
  print_r($matches);
  echo '</pre>';
}
Ainsi tu captures tous les caractères jusqu'au "</p>"
J'ai ajouté l'option "i" pour ignorer la casse et que cela prenne en compte aussi bien </p> que </P>
Il peut être nécessaire de rajouter l'option "U" (Ungreedy) pour qu'il s'arrête au premier </p> et non au dernier (je sais jamais quand il faut le mettre ou pas)
Tu peux aussi ajouter le premier "<p>" avant la parenthèse pour que celui-ci ne soit pas capturé et que ta chaine contienne uniquement la valeur du texte. Ou au contraire, mettre les parenthèses autour des <p>..</p> pour les capturer avec :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 531 Messages

22 avr. 2008, 19:01

Merci bien, j'y voit un peu plus clair, mais il y a un mais

Même avec la doc j'ai un peu du mal à comprendre cette fonction... Surtout le fait que le print_r me renvoi un tableau avec un doublon de la chaine récupéré, j'ai du mal à saisir pourquoi :

Array ( [0] =>
Et cette fois, voilà une description
Plus longue et avec un paragraphe en trop.
[1] =>
Et cette fois, voilà une description
Plus longue et avec un paragraphe en trop. )

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 avr. 2008, 08:35

C'est une question de nombre de parenthèses dans ton masque :
Si matches est fourni, il sera rempli par les résultats de la recherche. $matches[0] contiendra le texte qui satisfait le masque complet, $matches[1] contiendra le texte qui satisfait la première parenthèse capturante, etc.
Comme tu n'as qu'une seule parenthèse capturante, les index 0 et 1 ont la même valeur, mais tu pourrais avoir besoin de capturer plusieurs élément dans la chaine, ils se retrouveraient alors dans les index 1 à N, tandis que le 0 contiendrait l'ensemble tu texte qui correspondrait.
En gros "A(.*)B(.*)C" renverrait :
0 => Achaine1Bchaine2C
1 => chaine1
2 => chaine2
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

ViPHP
ViPHP | 4674 Messages

23 avr. 2008, 11:21

Hey :),

Attention au retour de preg_match qui peut valoir 0. C'est mieux de le tester avec une égalité stricte (===). Le script deviendrait alors :
if(0 === preg_match( ... )
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 531 Messages

23 avr. 2008, 18:58

Merci pour les explications. Finalement cette fonction est géniale, enfin on doit pouvoir faire un tas e chose quand on la maitrise bien =)

Sinon vous savez ou placer le Ungreedy ? Je trouve pas grand chose sur le net en rapport avec ça sur le net ou dans mon bouquin.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 avr. 2008, 23:09

Ungreedy est une option des expressions regulières, au même titre que le "i" de Ignore Case, et s'utilise donc de la même manière, placé juste après le masque :
"/mon_expression/Ui"
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 531 Messages

23 avr. 2008, 23:36

Ungreedy est une option des expressions regulières, au même titre que le "i" de Ignore Case, et s'utilise donc de la même manière, placé juste après le masque :
"/mon_expression/Ui"
Ah moi je voyais un truc plus compliqué que ça... merci =)
Il faut que je retrouve le site que j'avais vu une fois consacré aux expressions régulières.

Je peut rajouter quelquechose dans le masque pour que le texte soit capturé entre les balise <p> et </p> au lieux de capturer les balises avec ?
Car en fait c'est plus logique puisque je dois ensuite couper la chaine à x caractères. Il vaut mieux rajouter les balises après car si jamais la chaine est coupée en plein dans un </p> c'est pas terrible...

Si je me trompe pas on peut le faire avec une autre fonction, dont j'ai oublié le nom ou il suffirait de remplacer les balises par rien du tout, mais si on peut le faire directement dans le masque...

ViPHP
ViPHP | 4674 Messages

24 avr. 2008, 01:11

Deux adresses : expreg.com et lumadis.be.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Invité
Invité n'ayant pas de compte PHPfrance

24 avr. 2008, 14:42

En théorie le code suivant ne devrais pas me récupérer les balises <p> et </p> ?
#<p>(.*)</p>#Ui

Mammouth du PHP | 531 Messages

24 avr. 2008, 19:08

En théorie le code suivant ne devrais pas me récupérer les balises <p> et </p> ?
#<p>(.*)</p>#Ui
Oups j'ai oublié de me loguer :wink:

ViPHP
ViPHP | 4674 Messages

24 avr. 2008, 19:15

C'est exact. Il ne capture que ce qui est entre parenthèses (sauf si ce sont des parenthèses non-capturantes).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Invité
Invité n'ayant pas de compte PHPfrance

24 avr. 2008, 19:38

C'est exact. Il ne capture que ce qui est entre parenthèses (sauf si ce sont des parenthèses non-capturantes).
Justement... au résultat j'ai toujours les balises p dans la chaine.
Je pensais avoir mal compris. Donc ce sont des parenthèses non capturante ? (Par déduction ^^ )