【问题标题】:iterating SimpleXml xpath result迭代 SimpleXml xpath 结果
【发布时间】:2010-06-24 09:35:06
【问题描述】:

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

$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 的服务器上失败:
致命错误:在后/前递增/递减中用作数组的对象必须通过引用返回值

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

如果我可以让 xpath 在第一个 $result 中返回字段,一个解决方案可能是,这样我就不必迭代 $block[0]-&gt;Fields-&gt;Field 但我未能做出这样的 xpath 表达式。

【问题讨论】:

  • 请发布一个简短的、可重现的代码 sn-p。您可能错误地访问了元素。另外,错误信息与您发布的内容无关。
  • @Josh Davis:我已经更新了代码以提供一个可以开箱即用的示例,并且给出了同样的错误。
  • 谢谢,我一会儿看看。

标签: php xml xpath simplexml


【解决方案1】:

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

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

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

更新

我没有注意到您说您感兴趣的只是&lt;Field/&gt; 元素。在这种情况下,您可以直接通过 XPath 获取它:(记住它们都在数据命名空间中)

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

【讨论】:

    【解决方案2】:

    这可能是因为 $block 不是数组。您应该使用var_dumpprint_r 来确认这一点,然后在您的代码中使用is_array 以确保它是一个数组。

    如果 SimpleXML 找到多个具有相同名称的元素,它会返回一个对象数组。如果它找到一个元素,它只返回那个元素,而不是具有单个元素的数组。因此,当您期望多个元素时,您总是必须为只有一个元素的情况编写异常情况。

    【讨论】:

    • 我不确定您所说的“它返回一个对象数组”是什么意思。 xpath() 总是返回一个数组,并且通过对象表示法(例如$xml-&gt;Blocks)访问元素总是返回一个 SimpleXMLElement,无论它表示多少个元素,您可以在其上使用带有数字索引的数组表示法按顺序访问元素它们出现在文档中。在该示例中,您可以通过$xml-&gt;Blocks[0]-&gt;Block[0] 访问该块,即使每个块只有一个。不过,较旧版本的 SimpleXML 有一些特殊情况无法正常工作。
    猜你喜欢
    • 2021-09-29
    • 1970-01-01
    • 2011-08-12
    • 2011-12-12
    • 1970-01-01
    • 2013-11-11
    • 2012-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多