Цикл Foreach с xPath для объекта SimpleXML, возвращающего дублирующиеся данные - PullRequest
0 голосов
/ 11 марта 2012

Может ли кто-нибудь помочь мне объяснить, почему следующее возвращает дубликаты данных?

<?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 />';
}

Возвращает:

Mask: 1234
Mask: 1234

Если я добавлю print_r ($ array) в цикл foreach, я получу:

SimpleXMLElement Object
(
    [@attributes] => Array
        (
            [key] => 123
        )

    [string] => 1234
)
Mask: 1234

SimpleXMLElement Object
(
    [@attributes] => Array
        (
            [key] => 987
        )

    [string] => 5678
)
Mask: 1234

Что, черт возьми, происходит? Почему я получаю дублирующиеся маски, когда использую выражение xPath, когда оба массива $ явно не содержат дублирующиеся данные.

Ответы [ 3 ]

3 голосов
/ 11 марта 2012

Вы делаете один и тот же запрос xpath дважды, по одному разу для каждого из <array> узлов в вашем XML. Нет необходимости во внешнем цикле. Просто выполните запрос xpath, а затем зациклите его результаты.

$mask = $array->xpath('//string[@key="mask"]');
print 'Mask: ' . $mask[0] . '<br />';
print 'Mask: ' . $mask[1] . '<br />';

Или сначала выполните запрос xpath, затем выполните цикл:

$mask = $array->xpath('//string[@key="mask"]');
foreach ($mask as $m) {
   echo $m;
}
1 голос
/ 11 марта 2012

Начало пути расположения в xpath() с / делает его «абсолютным», тогда как вы хотите запросить «относительно» элемента $array. Для вашего примера просто возьмите //.

foreach ($load_test as $array)
{
    $mask = $array->xpath('string[@key="mask"]');

    print 'Mask: ' . $mask[0] . '<br />';
}

См. Также http://www.sitepoint.com/forums/showthread.php?723058-php-xml-loop&p=4778177&viewfull=1#post4778177

0 голосов
/ 11 марта 2012

До тех пор, пока я не смогу лучше понять, что происходит, я получаю следующие результаты; что позволяет мне сопоставлять ключевые атрибуты.

$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++;
}

Возвращает:

Mask: 1234
Name: mick

Mask: 5678
Name: bob

Не уверен, насколько ясно это, но в конечном итоге он делает то, что мне нужно.

...