2017-04-26 102 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。我已经指出了答案中的错误,我认为这很明显:打开''与关闭不匹配。开''不匹配结束''。您正确添加了关闭'',但未删除''。请做。 –