问题
Can anyone help explain to me why the following is returning duplicate data?
<?php
$xml_test = '<array key="results">
<array key="123">
<string key="mask">1234</string>
</array>
<array key="987">
<string key="mask">5678</string>
</array>
</array>';
$load_test = simplexml_load_string($xml_test);
foreach ($load_test as $array)
{
$mask = $array->xpath('//string[@key="mask"]');
print 'Mask: ' . $mask[0] . '<br />';
}
Returns:
Mask: 1234
Mask: 1234
If I throw a print_r($array) within the foreach loop, I get:
SimpleXMLElement Object
(
[@attributes] => Array
(
[key] => 123
)
[string] => 1234
)
Mask: 1234
SimpleXMLElement Object
(
[@attributes] => Array
(
[key] => 987
)
[string] => 5678
)
Mask: 1234
What the hell is going on? Why am I getting duplicate masks when I use an xPath expression when both of the $array quite clearly are not holding duplicate data.
回答1:
Starting the location path in xpath()
with /
makes it "absolute", whereas you want to query "relative" to the $array
element. For your example, just take out the //
.
foreach ($load_test as $array)
{
$mask = $array->xpath('string[@key="mask"]');
print 'Mask: ' . $mask[0] . '<br />';
}
See also http://www.sitepoint.com/forums/showthread.php?723058-php-xml-loop&p=4778177&viewfull=1#post4778177
回答2:
You are making the same xpath query twice, once for each of the <array>
nodes in your XML. There is no need for the outer loop. Just do your xpath query, then loop over its results.
$mask = $array->xpath('//string[@key="mask"]');
print 'Mask: ' . $mask[0] . '<br />';
print 'Mask: ' . $mask[1] . '<br />';
Or do the xpath query first, then loop over it:
$mask = $array->xpath('//string[@key="mask"]');
foreach ($mask as $m) {
echo $m;
}
回答3:
Until I can better understand what's going on, the following outputs what I am after; allowing me to match on the key attributes.
$xml_test = '<array key="results">
<array key="123">
<string key="mask">1234</string>
<string key="name">mick</string>
</array>
<array key="987">
<string key="mask">5678</string>
<string key="name">bob</string>
</array>
</array>';
$simplexml= new SimpleXMLElement($xml_test);
$test = $simplexml->xpath('//array/array');
$loop = 0;
foreach ($test as $result)
{
$mask = $result->xpath('//string[@key="mask"]');
$name = $result->xpath('//string[@key="name"]');
echo "Mask: " . $mask[$loop] . '<br />';
echo "Name: " . $name[$loop];
$loop++;
}
Returns:
Mask: 1234
Name: mick
Mask: 5678
Name: bob
Not sure how clean the above is, but it ultimately does what I need it to do.
来源:https://stackoverflow.com/questions/9652575/foreach-loop-with-xpath-on-simplexml-object-returning-duplicate-data