2010-05-26 4 views
18

Je suis la suggestion de cette question Robust, Mature HTML Parser for PHP, à propos de l'analyse du code HTML qui peut être malformé avec DOMDocument.Boucle sur DOMDocument

Y a-t-il un moyen facile de faire une boucle sur le document analysé? Donc, je voudrais boucler sur html comme ça.

$html='<ul> 
     <li>value1</li> 
     <li>value1</li> 
     <li>value3 
      <p>subvalue</p> 
     </li> 
     </ul> 
     <p>hello world</p>'; 

$doc = new DOMDocument(); 
$doc->loadHTML($html); 
??? 
foreach (??? as $node) 
{ 
    print $node->nodeName.':'.$node->nodeValue; 
} 

Et obtenir des résultats un peu comme ça.

ul: 
li:value1 
li:value2 
li:value3 
p:subvalue 
p:hello world 

L'utilisation de $doc->childNodes en lui-même ne fait pas vraiment ce que je veux. Comme il ne semble pas descendre aux branches inférieures de l'arbre. J'ai utilisé le code proposé par halfdan et je reçois des résultats comme celui-ci.

html: 
html:value1 
     value1 
     value3 
      subvalue 

     hello world 
+0

Les objets DOM peuvent (mais pas toujours) avoir une propriété appelée $ childNodes que vous pouvez parcourir. Vous pouvez vérifier la présence ou non de cette propriété avec la méthode hasChildNodes(). – GordonM

Répondre

25

Essayez ceci:

$doc = new DOMDocument(); 
$doc->loadHTML($html); 
showDOMNode($doc); 

function showDOMNode(DOMNode $domNode) { 
    foreach ($domNode->childNodes as $node) 
    { 
     print $node->nodeName.':'.$node->nodeValue; 
     if($node->hasChildNodes()) { 
      showDOMNode($node); 
     } 
    }  
} 
+0

Merci, j'ai mis à jour ma question pour être plus clair. Je ne crois pas '$ doc-> childNodes' fait ce que je veux. Fondamentalement, je veux visiter chaque nœud dans l'arbre, pas seulement voir tous les nœuds à un niveau. – Zoredache

+0

Très bien, donnez-moi une seconde et je mettrai à jour mon message. – halfdan

1

J'avais des problèmes avec des éléments qui ont des données c, où même des éléments qui n'ont des enfants où le retour qu'ils ont fait.

Je ne sais pas pourquoi c'était.

Le travail autour que j'ai trouvé changer

if($node->hasChildNodes()) { 
     showDOMNode($node); 
    } 

à

if($node->childNodes->length != 1) { 
     showDOMNode($node); 
    } 

Et le code fonctionne maintenant parfaitement.

2

Vous devez utiliser PHP Simple HTML DOM Parser et le code suivant:

<?php 
require_once 'simplehtmldom/simple_html_dom.php'; 

function iterateHtmlElements($html) 
{ 
    $dom = str_get_html($html); 
    $dom->set_callback('handleElement'); 
    $dom->__toString(); 
    echo "\n"; 
} 

function handleElement(simple_html_dom_node $elem) 
{ 
    if($elem->tag == 'text') { 
     echo $elem->innertext(); 
    } 
    else { 
     echo "\n" . $elem->tag . ": "; 
    } 
} 

$html='<ul> 
     <li>value1</li> 
     <li>value1</li> 
     <li>value3 
      <p>subvalue</p> 
     </li> 
     </ul> 
     <p>hello world</p>'; 
iterateHtmlElements($html); 

Il fonctionne exactement comme prévu. Je l'ai vérifié avec l'entrée que vous avez fourni et a obtenu les résultats suivants:

> php test2.php 

ul: 
li: value1 
li: value1 
li: value3 
p: subvalue 
p: hello world 
0

Une façon est de marcher l'arbre comme suit:

function next_node($node) 
{ 
    if($node->firstChild != null) 
    { 
     return $node->firstChild; 
    } 

    if($node->nextSibling != null) 
    { 
     return $node->nextSibling; 
    } 

    for($node = $node->parentNode; $node != null; $node = $node->parentNode) 
    { 
     if($node->nextSibling != null) 
     { 
      return $node->nextSibling; 
     } 
    } 

    return null; 
} 

for($node = $doc; $node != null; $node = next_node($node)) 
{ 
    // handle node (read-only mode, if you need read-write 
    // you have to save all the nodes in an array and then 
    // use that array 
    // 
    ... 
} 

Cela fonctionne pour la plupart des documents, mais il ressemble parfois le parentNode n'est pas configuré correctement et la fonction next_node() finit par retourner les informations erronées.