2014-09-23 18 views
1

我是XML和DOM的新手。我試圖從http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xmlDOM + XML Questions +發生了什麼?

獲取美元利率目前的代碼很好,但我沒有真正掌握髮生了什麼事情的幾個部分。

問題

  • 在XML文件中我看到幾個「的xmlns」的標籤,我知道這些都是命名空間,但我從來沒有遇到過,你有兩個場景。當我創建我的名稱空間引用器時,爲什麼它是我使用的最後一個名稱空間?

  • 當我選擇我的節點時,在我看來,要使用xDOM.selectNodes(「/ f:gesmes/f:gesmes/f:Cube」),但是這個和其他任何組合f:gesmes返回零(!)節點。我已經能夠訪問Cube節點的唯一方法是//表達式

  • 爲什麼代碼無法在沒有錯誤處理過程的情況下工作?如果沒有在錯誤恢復下的代碼裏噴出一個「對象變量或與塊未設置」錯誤

我的代碼

Option Explicit 

Private Sub run() ' run the whole operation' 

Dim http_req As http_req: Set http_req = New http_req 
Dim xDom As MSXML2.DOMDocument60 
Set xDom = New MSXML2.DOMDocument60 

Dim url As String: url = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml" 
xDom.async = False 
xDom.Load url 

Do Until xDom.ReadyState = READYSTATE_COMPLETE 
    DoEvents 
Loop 

Call find_ClassElement(xDom) 

End Sub 

Private Sub find_ClassElement(xDom As MSXML2.DOMDocument60) 

Dim ticker As String 
Dim if_USD As String 

Dim xDOM_element As MSXML2.IXMLDOMElement 
Dim xDOM_attribute As MSXML2.IXMLDOMAttribute 
Dim xDom_selection As MSXML2.IXMLDOMSelection 
Dim xDOM_nodeList As MSXML2.IXMLDOMNodeList 

xDom.setProperty "SelectionNamespaces", "xmlns:f='http://www.ecb.int/vocabulary/2002-08-01/eurofxref'" 

Set xDOM_nodeList = xDom.SelectNodes("//f:Cube") 

For Each xDOM_element In xDOM_nodeList 
     On Error Resume Next 
     if_USD = xDOM_element.Attributes(0).text 
     On Error GoTo 0 
     If if_USD = "USD" Then 
      ticker = xDOM_element.Attributes(1).text 
     End If 
     Next 
    Debug.Print ticker 
End Sub 

回答

2

關於問題#1,沒有什麼特別的多個名稱空間,許多XML都有它。沒有前綴的名稱空間(xmlns="....")被識別爲默認名稱空間。基本上具有默認名稱空間,所有後代節點和聲明默認名稱空間的節點都繼承相同的名稱空間。除非節點明確使用指向不同名稱空間URI的前綴,或者在本地聲明不同的默認名稱空間。

這就是爲什麼你需要註冊f前綴並使用它<Cube>節點儘管<Cube> s沒有前綴或命名空間聲明他們自己(因爲他們從父節點<gesmes:Envelope>繼承默認命名空間的原因。而Envelope節點它自身不在默認名稱空間中,因爲它有gesmes前綴)。

關於問題#2,如果你在XML仔細觀察,你會發現到最內側<Cube>節點的正確路徑是如下:

/gesmes:Envelope/f:Cube/f:Cube/f:Cube 

..你可能需要註冊gesmes命名空間前綴(連同f前綴),然後在XPath中使用它。

關於問題#3,你可以用純XPath表達式來獲得美元的匯率在一個更清潔&安全的方式:

//f:Cube[@currency='USD'] 

這個XPath告訴只返回<Cube>currency屬性值的節點等於USD

+0

+1我知道有一種更好的方式來使用XPath表達式來獲得美元利率。好答案! – 2014-09-24 13:48:49

1

我不是在這一個高手,但通常可以破解我的通過它的方式。正如我所看到的,Cube節點不是「gesmes」命名空間的一部分。這回答#2。

不幸的是,我不知道你的第一點的答案。

對於#3,這不是我將如何處理它,但你需要一種方法來處理沒有屬性的節點,或者不是你所期望的。你可以做:

For Each xDOM_element In xDOM_nodeList 
    If xDom_Element.attributes.length > 0 Then 
     if_USD = xDOM_element.attributes(0).Text 
    Else 
     if_USD = "" 
    End If 

    If if_USD = "USD" Then 
     ticker = xDOM_element.Attributes(1).text 
    End If 
    Debug.Print ticker 
Next