2010-07-19 5 views
0

Je dois obtenir tout le contenu de div class = "parent" à l'aide preg_match,Comment faire pour preg_match parent div?

<div class = "parent"> 

    <div id = "child1"> 
    </div> 

    <div id = "child2"> 
    </div> 

</div> 

Toute personne?

+1

Un autre qui essaie d'analyser HTML avec regex ... [Uh-oh] (http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454 # 1732454) ... – quantumSoup

+1

Voir la # 1 réponse: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags –

+0

Ceci est en fait un exercice donné par mon instructeur. nous prenons l'expression régulière atm. – Karl

Répondre

2

La bonne méthode consiste à utiliser the DOM et xpath pour cibler les éléments et attributs spécifiques que vous tentez d'extraire. Cependant, comme c'est le devoir, éduquons votre instructeur.

Étant donné que exacte chaîne, cette regex fonctionnera: !<div class = "parent">(.+)</div>!s

La clé est le modificateur "s". Il transforme le caractère "." de "n'importe quoi sauf un saut de ligne" en "n'importe quoi incluant un saut de ligne". Cependant, si les espaces ont été supprimés autour de =, cela se casserait. S'il y avait plus d'attributs, ça casserait. S'il y avait plus de noms de classe, cela casserait. En d'autres termes, c'est la pire façon de traiter le HTML jamais.

enfer, si le HTML ressemblait à ceci, il romprait:

<div> 
    <div class = "parent"> 
     My spoon is too big! 
     <div> 
      I am a banana! 
     </div><!-- Matches when un-greedy --> 
    </div> 
</div><!-- Matches when greedy --> 

Pourquoi? Parce que .+ est ce qu'on appelle "gourmand". Il correspondra à tout ce qu'il peut jusqu'à la prochaine clause. Cela signifie que tout ce qui est partagé entre div.parent et le commentaire gourmand. Bien qu'il puisse être rendu non-gourmand en ajoutant un point d'interrogation (.+?), alors il correspondrait à la première clause suivante possible, pas à la dernière clause suivante possible. Cela signifie que tout ce qui est partagé entre div.parent et le commentaire non-gourmand.

En raison des problèmes d'imbrication, les expressions régulières sont un outil très médiocre pour analyser le code HTML. Les problèmes que je vous ai montrés ici ne touchent que la surface du h̨̜̜̟̬̭͍o̶̻̹̥̻ͧ̆͆̊̉̍r̟͓ͨ͆ͨr̪̖̠̖̤̊̾ͣͦo̡̬͉͈͚̙͙ͯ͑ͨ͒ͥͩ̇ȓ̵̥̙͈̟s̠̏̊͠ qui vous attendent.

Veuillez, si possible, utiliser un véritable analyseur HTML/XML et travailler avec le DOM résultant. Cela sauvera votre santé mentale.

+0

+1 pour expliquer le modificateur 's'. Cela a été un problème pour moi à quelques reprises ces derniers temps, et j'avais oublié comment le résoudre! –

+0

Ok merci beaucoup. – Karl

0

Pour vos fins, ce sera probablement le faire, bien que ce n'est pas sans problème (comme indiqué dans les liens):

preg_match('/<div class = \'parent\'>(.*)<\/div>/s',$input,$matches); 

Après quoi, $ matches [0] contiendra le texte correspondant (y compris le parent div) et $ matches [1] contiendront uniquement les éléments internes.

+0

Merci beaucoup guyz. – Karl

0

vous vous retrouvez avec quelque chose de barbare comme ceci:

/<div[^>]+class ?= ?"parent"[^>]*>(\s*(?:<div.*<\/div>\s*)*)<\/div>/Us 

D'abord, la recherche dans la balise div d'ouverture pour la classe désirée - J'aime utiliser [^>] qui est un groupe de caractères spécifiant tout sauf un " > "personnage. Puis en tenant compte des espaces autour du "=" (ou non). Ensuite, l'idée de base est de jumeler chaque balise d'ouverture ultérieure avec son partenaire de fermeture afin de pouvoir s'arrêter au bon endroit. Ceci est fait avec un sous-masque non-capture qui peut répéter 0 ou plusieurs fois. Notez que cela ne fonctionne qu'avec un niveau d'imbrication. Pour faire face à cela, vous aurez besoin de récursivité et cela devient difficile à conceptualiser.

La version récursive ressemblerait à quelque chose comme ceci:

/<div[^>]+class ?= ?"parent"[^>]*>(\s*(<div.*(?2).*<\/div>\s*)*)<\/div>/Us 

Dans l'ensemble, si je ne pouvais pas faire la chose saine et utiliser le DOM je préfère marcher à travers la chaîne (à partir à chaque fois de la correspondance précédente) en incrémentant un compteur pour chaque balise div d'ouverture que j'ai rencontrée et en la décrémentant pour chaque balise de fermeture. Notez que ceux-ci sont hors de ma tête et posté pour apprendre à regex et pas avec l'idée que l'analyse HTML avec des expressions régulières est sain d'esprit. En outre, je détesterais voir un journal de la gymnastique que le moteur regex doit passer pour équilibrer tous ces caractères génériques.

Questions connexes