迭代 SimpleXml xpath 结果 [英] iterating SimpleXml xpath result

查看:29
本文介绍了迭代 SimpleXml xpath 结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 SimpleXMLElement 读取从远程服务器返回的 xml.然后使用 xpath 解析结果,如下所示:

I'm using SimpleXMLElement to read xml returned from a remote server. The results are then parsed with xpath like this:

$result = <<<XML
<DataImport2Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.xxx.xxx/Services/DataImport2"> 
    <Number /> 
    <Blocks> 
        <Block>
            <Code>Fbf</Code> 
            <Fields> 
                <Field> 
                    <Code>FinnsIFbf</Code> 
                    <Value>1</Value> 
                </Field>
            </Fields>
        </Block>
    </Blocks> 
</DataImport2Result>
XML;

$xml = new SimpleXMLElement($result);
$xml->registerXPathNamespace("data", array_pop($xml->getNamespaces()));

foreach($xml->xpath("//data:Code[.='Fbf']/..") as $block) {
    foreach($block[0]->Fields->Field as $field) {
        echo "Code: ". $field->Code ."\n"; // SHould return FinnsIFbf
    }
}

$result 是一个带有 SimpleXMLElement 对象的数组.尝试将 $block[0]->Fields(SimpleXMLElement object) 用作数组时会发生实际错误.所以结果就在那里.这是迭代的问题.
这在 PHP 5.3.2 中工作得很好,但在运行 5.1.6 的服务器上它失败了:
致命错误:用作后/前增量/减量中的数组的对象必须通过引用返回值

The $result is an Array with SimpleXMLElement objects. The actual error occurs when trying to use $block[0]->Fields(SimpleXMLElement object) as an array. So the results are there. It's iterating that is the problem.
This works just fine in PHP 5.3.2, but on the server which is running 5.1.6 it fails with:
Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference

在不升级服务器版本的情况下解决此问题的最简单方法是什么(服务器管理员认为更新版本不稳定")?

What's the simplest way to fix this without upgrading the server version (server admin thinks its "unstable" with a newer version)?

一个解决方案可能是,如果我可以让 xpath 在第一个 $result 中返回 Field,那么我不必迭代 $block[0]->Fields->Field 但是我没能做出这样的 xpath 表达式.

One solution could be if I could make the xpath return the Field in the first $result, so I wont have to iterate the $block[0]->Fields->Field but I failed to make such an xpath expression.

推荐答案

正如 Sjoerd 的回答中提到的,$block 不是数组.SimpleXMLElement::xpath() 返回一个对象数组,每个对象那些代表一个单一元素的对象.所以基本上,你必须用 $block 替换 $block[0] 因为它已经代表了你正在寻找的块.

As was mentionned in Sjoerd's answer, $block is not an array. SimpleXMLElement::xpath() returns an array of objects, each of those objects representing one single element. So basically, you have to replace $block[0] with $block since it already represents the block you're looking for.

另外,我已经重写了您的 XPath 表达式.由于您正在寻找 <data:Block/> 元素,这就是您的目标. 是一个谓词,所以它应该放在括号内.当然,在您的情况下,结果是相同的,但是使用语义正确的表达式是一种很好的做法,有助于在您重新阅读该代码(或者其他人必须维护它)时更清楚地了解稍后会发生什么.

Also, I have rewritten your XPath expression. Since you're looking for a <data:Block/> element, that's what you should target. The thing about <data:Code/> is a predicate, so it should go within brackets. Of course in your case the result is the same, but it's good practice to have semantically correct expressions, helps having a clearer idea of what's going on later on when you re-read that code (or if someone else has to maintain it.)

foreach ($xml->xpath('//data:Block[data:Code="Fbf"]') as $block) {
    foreach ($block->Fields->Field as $field) {
        echo "Code: ". $field->Code ."\n"; // SHould return FinnsIFbf
    }
}

<小时>

更新

我没有注意到您说您只对 元素感兴趣.这种情况下你可以直接通过XPath获取:(记住它们都在数据命名空间中)


Update

I didn't notice that you said that all you were interested in was the <Field/> element. In that case you can get it directly through XPath: (remember that they're all in the data namespace)

foreach ($xml->xpath('//data:Block[data:Code="Fbf"]/data:Fields/data:Field') as $field) {
    echo "Code: ". $field->Code ."\n"; // SHould return FinnsIFbf
}

这篇关于迭代 SimpleXml xpath 结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆