2017-04-26 30 views
1

這應該都是非常直接的,但由於某種原因它逃避了我。PHP從childNodes中提取getElementsByTagName

使用從文件導入以下XML結構:

<locations> 
    <devices> 
    <entry> 
     <serial>12345</serial> 
     <hostname>FooBarA</hostname> 
     <vsys> 
     <entry> 
      <displayname>CorpA</displayName> 
      <tag>InternalA</tag> 
     </entry> 
     </vsys> 
     </c> 
    </entry> 
    <entry> 
     <serial>123456</serial> 
     <hostname>FooBarB</hostname> 
     <vsys> 
     <entry> 
      <displayname>CorpB</displayName> 
      <tag>InternalB</tag> 
     </entry> 
     </vsys> 
     </c> 
    </entry> 
    </devices> 
</locations> 

並提取父母應該是直截了當:

$devices = $dom->getElementsByTagName('devices'); 
$data = array(); 
foreach($devices as $node){ // each $node = <devices> == only ONE object 
    foreach($node->childNodes as $child) { // each $child is the ENTIRE <entry>, including <entry> tag 
    // I would expect this to return the <serial> out of parent <entry>, but its not 
    $serial = $child->getElementsByTagName('serial') ; 
    echo "\n" . $count++ . ", a" .$serial->nodeName ;  
    if ($child->nodeName == "entry") { 
     // as a secondary method, I then try to extra <serial> looping through the childNodes of the parent <entry> and again, this doesn't work. 
     foreach ($child->childNodes as $kid) { 
     $serial = $kid->getElementsByTagName('serial') ; 
     echo ", b" .$serial->nodeName ; 
     } 
    } 
    } 
} 

上面打印出:

1a, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b 
2a, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b 
3a, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b 
4a, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b 

我實際的xml文件在serial級別有更多的兄弟姐妹,因此它的打印所有額外的b s ......因此,這告訴我基本的foreach正在工作,並且每個都正確地循環遍歷每個級別 - 但我無法在每個級別中提取nodeName或getElementsByTagName。

我想到兩種方法之一,在不同的嵌套級別,將提取<serial>,但都沒有工作。我在這裏錯過了什麼?

我的期望是它會打印:

1a 12345, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b 
2a 123456, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b 
3a 1234567, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b 
4a 12345678, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b 

或在miniumum:

1a, b 12345, b 12345, b 12345 ... 
2a, b 123456, b 123456, b 123456 ... 
3a, b 1234567, b 1234567, b 1234567 ... 
etc etc. 
+0

什麼是您預期的輸出? –

+0

$ child-> childNodes $ node-> childNodes ??? –

回答

1

getElementsByTagName返回DOMNodeList,所以你需要遍歷它得到各個節點的名稱:

$serials = $child->getElementsByTagName('serial') ; 
foreach($serials as $serial) { 
    echo "\n" . $count++ . ", a" .$serial->nodeName ;  
} 

作爲一個邊節點,問題中的xml不是vali d:

  • <displayname> ... </displayName>
  • <vsys> <entry> ... </entry> </c>
+0

在我的情況下,我需要將'serial'作爲其父'entry'的子集,並將它們分組在我的輸出中。所以我需要得到每個父'入口'並遍歷它的childNodes來提取'serial','hostname'並最終得到'vsys'中包含的每個子入口'entry'。我不能只是'getElementsByTagName('entry')',因爲這是抓住所有父和子'入口'。爲了方便您注意,爲什麼xml無效?我基本上顯示了爲路由器中的XPath API提取的完全相同的xml。 – rolinger

+0

嗯,我不會假裝我理解評論如何適用於我的答案。我將嘗試重新修改它:''serial = $ child-> getElementsByTagName('serial');'在你的代碼中是一個列表,它沒有你試圖打印的'nodeName'。如果您將此行替換爲我答案中的代碼片段,您將獲得預期的輸出結果。 –

+0

現在,關於無效的xml。我已經指出了答案中的錯誤,我認爲這很明顯:打開''與關閉不匹配。開''不匹配結束''。您正確添加了關閉'',但未刪除''。請做。 –