Php xpath迭代通过与其子项具有相同名称的父项

时间:2016-03-03 15:18:51

标签: php xml xpath

我有一个xml文件格式化这样的数据:

<area area_id="7" countrycode="" name="Europe">
    <area area_id="9" countrycode="ALB" name="Albania"/>
    <area area_id="12" countrycode="AND" name="Andorra"/>
    <area area_id="17" countrycode="ARM" name="Armenia"/>
    <area area_id="20" countrycode="AUT" name="Austria"/>
    <area area_id="21" countrycode="AZE" name="Azerbaijan"/>
    <area area_id="26" countrycode="BLR" name="Belarus"/>
    <area area_id="27" countrycode="BEL" name="Belgium"/>
    <area area_id="33" countrycode="BIH" name="Bosnia and Herzegovina"/>
    <area area_id="38" countrycode="BGR" name="Bulgaria"/>
    <area area_id="56" countrycode="HRV" name="Croatia"/>
    <area area_id="58" countrycode="CYP" name="Cyprus"/>
    <area area_id="59" countrycode="CZE" name="Czech Republic"/>
    <area area_id="61" countrycode="DNK" name="Denmark"/>
    <area area_id="68" countrycode="ENG" name="England"/>
    <area area_id="71" countrycode="EST" name="Estonia"/>
    <area area_id="73" countrycode="FRO" name="Faroe Islands"/>
    <area area_id="75" countrycode="FIN" name="Finland"/>
    <area area_id="76" countrycode="FRA" name="France"/>
    <area area_id="79" countrycode="GEO" name="Georgia"/>
    <area area_id="80" countrycode="DEU" name="Germany"/>
    <area area_id="82" countrycode="GRC" name="Greece"/>
</area>
<area area_id="92" countrycode="OTR" name="Other"/>
    <area area_id="93" countrycode="ISL" name="Iceland"/>
    <area area_id="98" countrycode="IRL" name="Republic of Ireland"/>
    <area area_id="99" countrycode="ISR" name="Israel"/>
    <area area_id="100" countrycode="ITA" name="Italy"/>
    <area area_id="104" countrycode="KAZ" name="Kazakhstan"/>
    <area area_id="111" countrycode="LVA" name="Latvia"/>
    <area area_id="116" countrycode="LIE" name="Liechtenstein"/>
</area>

我如何在php中使用xpath thoroug在每个父区域节点(可能有很多)及其子节点进行迭代。

这样的东西
foreach parent_area
    foreach parent_area->area
        do something

父母和孩子的名字让我感到困惑

2 个答案:

答案 0 :(得分:1)

根据使用情况,这有两种方式。您可以嵌套表达式并使用外部表达式中的节点作为内部表达式的上下文。

$xml = <<<'XML'
<root>
  <area area_id="7" countrycode="" name="Europe">
    <area area_id="9" countrycode="ALB" name="Albania"/>
    <area area_id="12" countrycode="AND" name="Andorra"/>
    <area area_id="17" countrycode="ARM" name="Armenia"/>
    <area area_id="20" countrycode="AUT" name="Austria"/>
  </area>
  <area area_id="92" countrycode="OTR" name="Other">
    <area area_id="93" countrycode="ISL" name="Iceland"/>
    <area area_id="98" countrycode="IRL" name="Republic of Ireland"/>
    <area area_id="99" countrycode="ISR" name="Israel"/>
  </area>
</root>
XML;

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);

foreach ($xpath->evaluate('/*/area') as $area) {
  echo $area->getAttribute('name'), "\n";
  foreach ($xpath->evaluate('area', $area) as $subArea) {
    echo '* ', $subArea->getAttribute('name'), "\n";
  }
}

输出:

Europe
* Albania
* Andorra
* Armenia
* Austria
Other
* Iceland
* Republic of Ireland
* Israel

或者您在单个表达式中组合多个位置路径,一次获取所有节点。如果您有多个嵌套级别,这将非常有用。

foreach ($xpath->evaluate('/*/area|/*//area[parent::area]') as $area) {
  echo str_repeat('* ', $xpath->evaluate('count(ancestor::area)', $area));
  echo $area->getAttribute('name'), "\n";
}

答案 1 :(得分:0)

如果您使用<root>元素将XML括起来,并修复XML有效(请注意&#39; /&#39;在&#39;其他&#39; in的标记的末尾我的代码):

<root>
    <area area_id="7" countrycode="" name="Europe">
    ...
    <area area_id="92" countrycode="OTR" name="Other">
        ...
        <area area_id="116" countrycode="LIE" name="Liechtenstein"/>
    </area>
</root>

,您可以使用Xpath遍历XML,例如使用以下代码:

$str = file_get_contents(<file>);
$xml = new SimpleXMLElement($str);
$result = $xml->xpath('/root/area');
while(list( , $node) = each($result)) {
    foreach ($node->attributes() as $a => $b) {
        echo "{$a} -> {$b}<br />\n";
    }
    $result2 = $node->xpath('area');
    while(list( , $node2) = each($result2)) {
        foreach ($node2->attributes() as $a => $b) {
            echo "---> {$a} -> {$b}<br />\n";
        }
    }
}