2010-05-26 21 views
18

Sto seguendo il suggerimento di questa domanda Robusto, Mature HTML Parser for PHP, sull'analisi di html che potrebbe non essere corretto con DOMDocument.Loop over DOMDocument

Esiste un modo semplice per eseguire il loop del documento analizzato? Quindi mi piacerebbe eseguire il loop su html come questo.

$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; 
} 

E ottenere risultati in questo modo.

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

Utilizzando $doc->childNodes di per sé in realtà non fare quello che voglio. Dal momento che non sembra scendere ai rami più bassi nell'albero. Ho usato il codice suggerito da halfdan e ottengo risultati come questo.

html: 
html:value1 
     value1 
     value3 
      subvalue 

     hello world 
+0

Gli oggetti DOM possono (ma non sempre) avere una proprietà chiamata $ childNode su cui è possibile scorrere. È possibile verificare la presenza o meno di questa proprietà con il metodo hasChildNodes(). – GordonM

risposta

25

Prova questa:

$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

Grazie, ho aggiornato la mia domanda per essere più chiara. Non credo che '$ doc-> childNodes' di per sé faccia ciò che voglio. Fondamentalmente voglio visitare ogni nodo dell'albero, non solo vedere tutti i nodi a un livello. – Zoredache

+0

OK, dammi un secondo e aggiornerò il mio post. – halfdan

1

stavo avendo problemi con gli elementi che hanno avuto i dati c, dove anche gli elementi che non hanno bambini in cui ritornano che hanno fatto.

Non sono sicuro del motivo.

Il lavoro in giro ho trovato è stato quello di cambiare

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

a

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

E il codice ora funziona perfettamente.

2

È necessario utilizzare PHP Simple HTML DOM Parser e il seguente codice:

<?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); 

funziona esattamente come previsto. Ho controllato con l'ingresso che hai fornito ed ha ottenuto i seguenti risultati:

> php test2.php 

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

Un modo è quello di camminare l'albero come segue:

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 
    // 
    ... 
} 

Questo funziona per la maggior parte dei documenti, tuttavia sembra che a volte il parentNode non è in qualche modo impostato correttamente e la funzione next_node() termina la restituzione delle informazioni errate.