我对XML和DOM很陌生。我试图从http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
获取美元汇率这段代码现在很有用,但我并没有真正掌握所发生的几个部分。
问题
在XML文件中,我看到了几个" xmlns"标签,我知道这些是用于命名空间的,但我从未遇到过你有两个的情况。当我创建我的命名空间引用器时,为什么它是我使用的最后一个命名空间?
当我选择我的节点时,我认为要进入Cube节点我应该使用xDOM.selectNodes(" / f:gesmes / f:gesmes / f:Cube&#34 ;)但是这个和f:gesmes的任何其他组合返回零(!)节点。我能够访问多维数据集节点的唯一方法是使用//表达式
为什么没有错误处理程序代码不起作用?没有On Error Resume接下来代码会发出一个"对象变量或者没有设置块"错误
我的代码
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
答案 0 :(得分:2)
关于问题#1,没有什么特别的,有多个名称空间,许多XML都有它。没有前缀(xmlns="...."
)的命名空间被识别为默认命名空间。基本上具有默认命名空间,所有后代节点和声明默认命名空间的节点都继承相同的命名空间。除非节点明确使用指向不同名称空间URI的前缀,或者在本地声明了不同的默认名称空间。
这就是为什么你需要注册f
前缀并将其用于<Cube>
节点的原因,尽管<Cube>
没有自己的前缀或命名空间声明(因为它们从父节点<gesmes:Envelope>
继承了默认命名空间。而且它自己的Envelope
节点不在默认命名空间中,因为它有gesmes
前缀。
关于问题#2,如果仔细查看XML,您将看到最内层<Cube>
节点的正确路径如下:
/gesmes:Envelope/f:Cube/f:Cube/f:Cube
..在XPath中使用之前,您可能需要注册gesmes
命名空间前缀(以及f
前缀)。
关于问题#3,您可以使用纯XPath表达式来获得更清晰的美元汇率。更安全的方式:
//f:Cube[@currency='USD']
此XPath告诉只返回<Cube>
属性值等于currency
的{{1}}个节点。
答案 1 :(得分: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