2013-08-25 33 views
2

我從http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml如何通過屬性選擇xml元素而無需迭代使用PHP?

<?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> 

這個XML(我刪除示範目的的一些值),我想要得到的轉換率,爲讓說,GBP使用PHP

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

*沒有工作*在哪種方式,完全是? – michi

+0

我剛收到一個空數組 –

+0

也許是因爲XML中沒有'RUB'? – michi

回答

3

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規格以下摘錄:

前綴提供了合格的名稱的命名空間前綴部分,並且必須與命名空間相關聯名稱空間聲明中的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

如果我們查看元素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的任何元素。

+0

它的作品,真棒!我不明白gesmes是如何不相關的,因爲它甚至在根節點...兩個命名空間使我困惑,我需要閱讀背後的理論!謝謝! –

+1

每個元素都在一個命名空間中,而不管它的祖先是什麼。在本文檔中,以'gesmes:'爲前綴的節點在一個命名空間中,而沒有前綴的節點在另一個命名空間中(「默認」命名空間)。使用XPath,只需指定要查找的元素的名稱空間,而不管該文檔包含哪些內容。 – IMSoP

+0

真棒,非常感謝你,現在我終於明白了! @IMSop –

相關問題