2017-03-03 43 views
1

我想我會寫一個簡單的函數來訪問DOM樹中的所有節點。我寫了它,給它一個不太複雜的XML工作,但是當我運行它時,我只獲得了頂級(DOMDocument)節點。XML:爲什麼我的DOM遍歷函數只產生頂級節點?

請注意,我使用PHP的生成語法: http://php.net/manual/en/language.generators.syntax.php

這裏是我的功能:

function DOMIterate($node) 
{ 
    yield $node; 
    if ($node->hasChildNodes()) 
    { 
     foreach ($node->childNodes as $subnode) { 
      // if($subnode != null) { 
       DOMIterate($subnode); 
      // } 
     } 
    } 
} 

,這是應該打印結果的測試用例代碼:

$doc = new DOMDocument(); 
    $doc->loadXML($input); 

    foreach (DOMIterate($doc) as $node) { 
     $type = $node->nodeType; 
     if ($type == XML_ELEMENT_NODE) { 
      $tag = $node-> tagName; 
      echo "$tag\n"; 
     } 
     else if ($type == XML_DOCUMENT_NODE) { 
      echo "document\n"; 
     } 
     else if ($type == XML_TEXT_NODE) { 
      $text = $node->wholeText; 
      echo "text: $text\n"; 
     } else { 
      $linenum = $node->getLineNo(); 
      echo "unknown node type: $type at input line $linenum\n"; 
     } 
    } 

的輸入XML是前18行 https://www.w3schools.com/xml/plant_catalog.xml 加上a如果您使用PHP7關閉

+0

嗯......只是想的東西。是否禁止「生成器」函數遞歸調用?如果是這樣,任何人都有一個將會遍歷遞歸結構的「生成器」的例子嗎? –

回答

0

,你可以試試這個:

<?php 

$string = <<<EOS 
<div level="1"> 
    <div level="2"> 
     <p level="3"></p> 
     <p level="3"></p> 
    </div> 
    <div level="2"> 
     <span level="3"></span> 
    </div> 
</div> 
EOS; 

$document = new DOMDocument(); 
$document->loadXML($string); 

function DOMIterate($node) 
{ 
    yield $node; 
    if ($node->childNodes) { 
     foreach ($node->childNodes as $childNode) { 
      yield from DOMIterate($childNode); 
     } 
    } 
} 

foreach (DOMIterate($document) as $node) { 
    echo $node->nodeName . PHP_EOL; 
} 

這裏有一個工作的例子 - http://sandbox.onlinephpfunctions.com/code/ab4781870f8f988207da78b20093b00ea2e8023b 請記住,你還可以得到那些包含在標籤內的文本節點。

+0

當我嘗試他們時,來自Barmar和motanelu的(相當)答案起作用。謝謝。 –

0

在由發生器調用的函數中使用yield不會將該值返回給原始發生器的調用者。您需要使用yield from將值傳回。

function DOMIterate($node) 
{ 
    yield $node; 
    if ($node->hasChildNodes()) 
    { 
     foreach ($node->childNodes as $subnode) { 
      // if($subnode != null) { 
       yield from DOMIterate($subnode); 
      // } 
     } 
    } 
} 

這需要PHP 7.如果您使用的是較早的版本,請參閱Recursive generators in PHP