使用 VBA 解析 XML 文档 (MSXML V6.0)

Parsing XML document using VBA (MSXML V6.0)

我正在尝试直接解析来自 SEC 的财务信息,并且对使用 excel 中的 VBA 解析 XML 文件有疑问。我知道可以通过引用子节点和项目编号的文档来工作,但是文档很大,需要很长时间才能通读并确定我需要的每个项目。

我在网上看到,使用 XPATH 可以更高效地查询 XML 文档。我尝试了很多方法,但到目前为止还没有成功。我相信我的问题是了解元素位于哪个命名空间以及如何正确引用指定命名空间下的元素。

下面是我尝试引用任意元素的部分代码,

Sub SecData()

Dim xml_obj As MSXML2.XMLHTTP60
Dim xDoc As New MSXML2.DOMDocument60
Dim xml_url As String
Dim nodes As Variant

Set xml_obj = New MSXML2.XMLHTTP60

xml_url = "https://www.sec.gov/Archives/edgar/data/320193/000032019321000010/aapl-20201226_htm.xml"
xml_obj.Open bstrMethod:="GET", bstrURL:=xml_url
xml_obj.send

xDoc.LoadXML (xml_obj.responseText)

xDoc.SetProperty "SelectionLanguage", "XPath"
xDoc.SetProperty "SelectionNamespaces", "xmlns:link='http://www.xbrl.org/2003/linkbase'"

nodes = xDoc.SelectNodes("//RevenueFromContractWithCustomerExcludingAssessedTax")

XML 文档太大,无法包含在问题中,所以我将在下面留下 link,

https://www.sec.gov/Archives/edgar/data/320193/000032019321000010/aapl-20201226_htm.xml

如有任何帮助,我们将不胜感激!

谢谢

XML: do child nodes inherit parent's namespace prefix? 涵盖命名空间继承。

如果命名空间没有像这样的前缀:

 xmlns="http://www.xbrl.org/2003/instance"

然后它会被它下面的任何东西继承。

如果有前缀(这里是“xbrldi”)

 xmlns:xbrldi="http://xbrl.org/2006/xbrldi"

那么只有在元素中显式使用时才会被继承,例如:

<xbrldi:explicitMember dimension="us-gaap:StatementClassOfStockAxis">

您查询中的元素将“us-gaap”作为命名空间别名,因此您需要将其添加到命名空间集合中,并将该别名包含在您的 xpath 中:

us-gaap:RevenueFromContractWithCustomerExcludingAssessedTax

例如:

Dim xDoc As New MSXML2.DOMDocument60
Dim nodes As Variant

xDoc.resolveExternals = False  'don't try to resolve external resources
xDoc.validateOnParse = True

xDoc.Load "C:\Temp\aapl-20201226_htm.xml"  'using local copy for testing...

Debug.Print xDoc.parseError.reason 'in case of problems

xDoc.SetProperty "SelectionLanguage", "XPath"

'add namespaces: the first one is the default namespace with a "dummy" prefix of "xxx"
xDoc.SetProperty "SelectionNamespaces", _
                "xmlns:xxx='http://www.xbrl.org/2003/instance' " & _
                "xmlns:link='http://www.xbrl.org/2003/linkbase' " & _
                "xmlns:us-gaap='http://fasb.org/us-gaap/2020-01-31'"
                '+ other namespaces as needed...

'element with no prefix: using the "dummy" `xxx` prefix we added for the default namespace
Set nodes = xDoc.SelectNodes("//xxx:context")
Debug.Print nodes.Length  ' 207

'these elements belong to a specific namespace so use that prefix...
Set nodes = xDoc.SelectNodes("//us-gaap:RevenueFromContractWithCustomerExcludingAssessedTax")
Debug.Print nodes.Length  ' 28