如何在VBA中获取ECB汇率XML里父Cube节点的time属性值?
问题描述
通过GET请求获取欧洲中央银行的每日汇率XML数据,需要提取包含time属性的父Cube节点的time值,以此判断是否需要将汇率存入数据库。现有VBA代码能正常提取汇率和货币代码,但无法获取该父节点的time属性,请求解决方法。
XML核心结构示例:
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> <Cube> <Cube time="2023-01-06"> <Cube currency="USD" rate="1.0500"/> <!-- 其他汇率节点 --> </Cube> </Cube> </gesmes:Envelope>
现有VBA代码片段:
Dim xhr As Object, node As Object Set exchangeRates = New Collection Set xhr = CreateObject("msxml2.xmlhttp.6.0") xhr.Open "GET", "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml", False xhr.Send For Each node In xhr.responseXML.SelectNodes("//*[@rate]") exchangeRates.Add Conversion.Val(node.GetAttribute("rate")), node.GetAttribute("currency") lb_CurrencySelection.AddItem node.GetAttribute("currency") Next
解决方法
核心问题是XML存在默认命名空间(xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"),直接使用SelectNodes会因命名空间不匹配无法定位节点。需先给默认命名空间注册前缀,再通过前缀查询节点。
步骤1:注册命名空间前缀
在获取XML响应后,为默认命名空间绑定一个自定义前缀(比如ecb):
xhr.responseXML.setProperty "SelectionNamespaces", "xmlns:ecb='http://www.ecb.int/vocabulary/2002-08-01/eurofxref'"
步骤2:获取父Cube节点的time值
通过注册的前缀,使用SelectSingleNode定位带time属性的Cube节点(每日XML仅存在一个该节点):
Dim timeNode As Object Dim rateDate As String Set timeNode = xhr.responseXML.SelectSingleNode("//ecb:Cube[@time]") If Not timeNode Is Nothing Then rateDate = timeNode.GetAttribute("time") ' 此处可加入日期判断逻辑:比如对比数据库已有日期,决定是否存储后续汇率 Debug.Print "汇率日期:" & rateDate End If
完整修改后的代码
Dim xhr As Object, node As Object, timeNode As Object Dim exchangeRates As Collection Dim rateDate As String Set exchangeRates = New Collection ' 发送GET请求获取XML数据 Set xhr = CreateObject("msxml2.xmlhttp.6.0") xhr.Open "GET", "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml", False xhr.Send ' 注册默认命名空间前缀 xhr.responseXML.setProperty "SelectionNamespaces", "xmlns:ecb='http://www.ecb.int/vocabulary/2002-08-01/eurofxref'" ' 获取汇率日期 Set timeNode = xhr.responseXML.SelectSingleNode("//ecb:Cube[@time]") If Not timeNode Is Nothing Then rateDate = timeNode.GetAttribute("time") Debug.Print "当前汇率日期:" & rateDate ' 加入你的日期校验逻辑,比如检查数据库是否已存在该日期数据 End If ' 遍历并存储汇率数据 For Each node In xhr.responseXML.SelectNodes("//ecb:Cube[@rate]") exchangeRates.Add Conversion.Val(node.GetAttribute("rate")), node.GetAttribute("currency") lb_CurrencySelection.AddItem node.GetAttribute("currency") Next ' 清理对象 Set xhr = Nothing Set timeNode = Nothing Set node = Nothing Set exchangeRates = Nothing
关键说明
- 命名空间必须注册:XML的默认命名空间不会被自动识别,
SelectNodes/SelectSingleNode必须通过前缀才能匹配到目标节点。 - 使用
SelectSingleNode更高效:每日汇率XML仅包含一个带time属性的Cube节点,无需用SelectNodes遍历。
内容的提问来源于stack exchange,提问作者bot.rubiks
相关产品推荐
相关产品推荐

