Reputation: 430
I have an xml file that formats data like this:
<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>
How do i iterate in php with xpath thoroug every parent area node(there can be many) and their children.
Something like
foreach parent_area
foreach parent_area->area
do something
Same names of parent and children are confusing me
Upvotes: 0
Views: 53
Reputation: 19512
Here are two ways depending on the usage. You can nest the expression and use the node from the outer expression as an context for the inner expression.
$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";
}
}
Output:
Europe
* Albania
* Andorra
* Armenia
* Austria
Other
* Iceland
* Republic of Ireland
* Israel
Or you combine several locations paths in a single expression an fetch all nodes at once. This is useful if you have several nesting levels.
foreach ($xpath->evaluate('/*/area|/*//area[parent::area]') as $area) {
echo str_repeat('* ', $xpath->evaluate('count(ancestor::area)', $area));
echo $area->getAttribute('name'), "\n";
}
Upvotes: 1
Reputation: 1899
If you enclose XML above with <root>
element, and fix XML to be valid (please note missing '/' at the end of tag of 'Other' in my code):
<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>
, you can traverse the XML with Xpath using for example this code:
$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";
}
}
}
Upvotes: 0