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


How can I select an xml element by attribute without iterating using PHP?

我从http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.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。

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

$XML=simplexml_load_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
    foreach($XML->Cube->Cube->Cube as $rate){
...

但我想在不迭代的情况下获得值,而且我真的不想使用regex。。。

我试过这样的东西,但没用:

$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"]');

Cube元素不在前缀为gesmeshttp://www.gesmes.org/xml/2002-08-01命名空间中,它们在默认命名空间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"]');

这是一个实时演示,显示了具有更正名称空间的结果计数为1。


为了给这一点一个权威的解释,请考虑以下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;本地名称";是CCD_ 9。

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

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