如何在不使用PHP迭代的情况下按属性选择xml元素?

时间:2013-08-25 18:45:28

标签: php xml xpath simplexml

我有来自http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml

的XML
<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time='2013-08-23'>
            <Cube currency='USD' rate='1.3355'/>
            <Cube currency='GBP' rate='0.85910'/>
            <Cube currency='HUF' rate='298.98'/>
        </Cube>
    </Cube>
</gesmes:Envelope>

(为了示范目的,我删除了一些值)

我想获得转换率,比如说,使用PHP的GBP。

HI可以使用simplexml加载它,如下所示:

$XML=simplexml_load_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");

    foreach($XML->Cube->Cube->Cube as $rate){
...

但是我想在没有迭代的情况下得到这个值,而且我真的不想使用正则表达式...

我尝试了类似的东西,但它没有用:

$sxe=simplexml_load_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");

$sxe->registerXPathNamespace('c', 'http://www.gesmes.org/xml/2002-08-01');
$result = $sxe->xpath('//c:Cube[@currency="USD"]');

1 个答案:

答案 0 :(得分:4)

Cube元素不在http://www.gesmes.org/xml/2002-08-01命名空间中,它已被赋予前缀gesmes,它们位于默认命名空间中,即http://www.ecb.int/vocabulary/2002-08-01/eurofxref

因此而不是:

$sxe->registerXPathNamespace('c', 'http://www.gesmes.org/xml/2002-08-01');
$result = $sxe->xpath('//c:Cube[@currency="USD"]');

您需要注册其他命名空间:

$sxe->registerXPathNamespace('c', 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref');
$result = $sxe->xpath('//c:Cube[@currency="USD"]');

以下是a live demo showing a result count of 1,其中包含更正后的命名空间。


要尝试给出权威性解释,请考虑以下Namespaces in XML规范的摘录:

  

Prefix提供限定名称的名称空间前缀部分,并且必须与名称空间声明中的名称空间URI引用相关联[...]注意,前缀仅用作命名空间名称的占位符。

     

与前缀元素或属性名称对应的扩展名称具有前缀绑定到的URI作为其名称空间名称[...]

     

默认名称空间声明适用于其范围内所有未加前缀的元素名称。

     

如果作用域中存在默认名称空间声明,则对应于未加前缀元素名称的扩展名称将默认名称空间的URI作为其名称空间名称。如果作用域中没有默认名称空间声明,则名称空间名称没有值。 [...]在所有情况下,本地名称与未加前缀的名称本身相同。

元素Cube没有前缀,因此我们寻找范围内的默认命名空间声明;到达最外层元素,我们找到xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref",因此Cube元素的“命名空间名称”是URI http://www.ecb.int/vocabulary/2002-08-01/eurofxref,“本地名称”是Cube。< / p>

如果我们查看元素gesmes:Sender,我们会看到它有一个前缀gesmes,所以我们会寻找该前缀的定义。查找xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01",我们会得出结论,“扩展名称”包含“命名空间名称”http://www.gesmes.org/xml/2002-08-01和“本地名称”Sender

为了在XPath中使用这些“命名空间名称”,我们必须为XPath表达式分配前缀,这些前缀不需要与实际文档中的前缀相对应。在这种情况下,我们选择为名称空间http://www.ecb.int/vocabulary/2002-08-01/eurofxref分配前缀c,以便表达式//c:Cube将匹配任何具有http://www.ecb.int/vocabulary/2002-08-01/eurofxref的“名称空间名称”的元素和Cube的“本地名称”。