Foreach loop with xPath on SimpleXML object returning duplicate data

*爱你&永不变心* 提交于 2019-12-25 06:52:15

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!