Php循环遍历Xml节点

时间:2015-01-21 10:51:52

标签: php xml xpath domdocument

我有像

这样的Xml文件
<response>
<tag1>
    <item>
        <id>106</id>
        <title>DG</title>
    </item>
    <item>
        <id>105</id>
        <title>AC</title>
    </item>
</tag1>
<tag2>
    <item>
        <id>1</id>
        <title>DjG</title>
    </item>
    <item>
        <id>15</id>
        <title>AoC</title>
    </item>
</tag2>
</response>

我尝试使用此代码来提取ID和标题

$dom = new DomDocument();
    $dom->load('xml.xml');
    $xpath = new DOMXPath($dom);

    foreach($xpath->evaluate('//response/*') as $node){
    $params =$xpath->evaluate('//response/' .$node->nodeName . '/item/*');
        foreach($params as $child) {
            echo $node->nodeName ." = " .$child->nodeName ." = " .$child->nodeValue ."\n<br>";
        }
    }

但我得到了结果

<br>tag1 = id = 106
<br>tag1 = title = DG
<br>tag1 = id = 105
<br>tag1 = title = AC
<br>tag2 = id = 1
<br>tag2 = title = DjG
<br>tag2 = id = 15
<br>tag2 = title = AoC

但我需要这样做

  


tag1 = 106 = DG       
tag1 = 105 = AC       
tag2 = 1 = DjG       
tag2 = 15 = AoC

3 个答案:

答案 0 :(得分:2)

在第二个foreach上,只定位$node->nodeName,然后在内部foreach目标上标识每个标题。

foreach($xpath->evaluate('//response/*') as $node) {
    $tag = $node->nodeName;
    $params = $xpath->evaluate("//$tag/*");
    foreach($params as $child) {
        $id = $xpath->evaluate('string(./id)', $child);
        $title = $xpath->evaluate('string(./title)', $child);
        echo $tag ." = " .$id ." = " .$title ."\n<br>";
    }
}

Sample Output

SimpleXML版本:

$xml = simplexml_load_file('xml.xml');
foreach($xml as $tag =>$node) {
    foreach($node as $item => $child) {
        echo $tag ." = " .$child->id ." = " .$child->title ."\n<br>";
    }
}

Sample Output

答案 1 :(得分:1)

使用此代码:

$dom = new DomDocument();
$dom->load('xml.xml');
$xpath = new DOMXPath($dom);
foreach($xpath->evaluate('//response/*') as $node){
    $params =$xpath->evaluate('//response/' .$node->nodeName . '/*');

     foreach($params as $child) 
    {
       echo $node->nodeName ." = " .$child->getElementsByTagName('id')->item(0)->textContent ." = " .$child->getElementsByTagName('title')->item(0)->textContent  ."\n<br>";
    }
}

答案 2 :(得分:1)

DOMXpath :: evaluate()的第二个参数是上下文节点。如果不使用斜杠启动XPath表达式,则它将相对于它。因此,在循环中,您通常希望使用当前节点作为表达式的上下文。

foreach ($xpath->evaluate('/absolute-expression') as $node) {
  var_dump(
     $xpath->evaluate('relative-expression', $node)
  );
}

XPath(与CSS选择器不同)可以沿不同的轴获取元素的属性。您可以使用以下命令获取父节点的本地名称(不带名称空间前缀)。

local-name(parent::*)

使用它,您可以通过迭代item元素的单个循环来解决问题。

示例:

$dom = new DomDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);

foreach ($xpath->evaluate('//response/*/item') as $node) {
  echo 
    $xpath->evaluate('local-name(parent::*)', $node), ' = ',
    $xpath->evaluate('string(id)', $node), ' = ',
    $xpath->evaluate('string(title)', $node), "\n";
}

输出:

tag1 = 106 = DG
tag1 = 105 = AC
tag2 = 1 = DjG
tag2 = 15 = AoC

仅限,如果需要为每个第一级节点(tag1,tag2)调用source。你需要两个循环。就像输出由标签*元素节点分组的项目一样。

$dom = new DomDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);

foreach ($xpath->evaluate('//response/*') as $node) {
  echo  
    $xpath->evaluate('local-name()', $node), 
    "\n--------\n";
  foreach ($xpath->evaluate('item', $node) as $item) {
    echo 
      $xpath->evaluate('string(id)', $item), ' = ',
      $xpath->evaluate('string(title)', $item), "\n";
  }
  echo "\n";
}

输出:

tag1
--------
106 = DG
105 = AC

tag2
--------
1 = DjG
15 = AoC