Ber*_*nes 3 xml excel parsing vba domdocument
我需要解析数百个具有相同结构的 XML 文件,如下所示:
\n\n<?xml version="1.0" encoding="UTF-8"?>\n <Concepts>\n <ConceptModel name="food">\n <Filters>\n <Filter type="CC"/>\n </Filters>\n <Queries>\n <Query lang="EN">(cheese, bread, wine)</Query>\n <Query lang="DE">(K\xc3\xa4se, Brot, Wein)</Query>\n <Query lang="FR">(fromaige, pain, vin)</Query>\n </Queries>\n </ConceptModel>\n </Concepts>\nRun Code Online (Sandbox Code Playgroud)\n\n我在互联网上阅读了几篇文章和帖子,如下所示,但我无法想出解决方案:
\n\n\n\n到目前为止我正在做:
\n\n\n\n<?xml version="1.0" encoding="UTF-8"?>\n <Concepts>\n <ConceptModel name="food">\n <Filters>\n <Filter type="CC"/>\n </Filters>\n <Queries>\n <Query lang="EN">(cheese, bread, wine)</Query>\n <Query lang="DE">(K\xc3\xa4se, Brot, Wein)</Query>\n <Query lang="FR">(fromaige, pain, vin)</Query>\n </Queries>\n </ConceptModel>\n </Concepts>\nRun Code Online (Sandbox Code Playgroud)\n\n这段代码似乎可以被VBA理解,但它不读取内容。循环不会被读取,这意味着(我猜)查询根本没有循环。事实证实了这一点Msgbox "how many queries"。但实际上有三个查询。有人可以帮我吗?
作为第二个问题我想问一下
\n\nDim oXml As MSXML2.DOMDocument\nSet oXml = New MSXML2.DOMDocument\noXml.LoadXML ("C:\\folder\\folder\\name.xml")\n\nDim Queries As IXMLDOMNodeList\nDim Query As IXMLDOMNode\n\nThisWorkbook.Sheets(3).Cells(i, 1) = "before loop"\n\nSet Queries = oXml.SelectNodes("/concepts/Queries")\n\nMsgBox "how many Queries " & Queries.Length\n\nFor Each Query In Queries\n ThisWorkbook.Sheets(3).Cells(i, 1) = "Works"\n ThisWorkbook.Sheets(3).Cells(i, 2) = Query.SelectNodes("Query").iTem(0).Text\n i = i + 1\nNext\nRun Code Online (Sandbox Code Playgroud)\n\n会是一样的
\n\n Dim oXml As MSXML2.DOMDocument\nRun Code Online (Sandbox Code Playgroud)\n\n自从我签入工具/参考文献“Microsof XML,v6.0”以来
\n\n我认为具有标签 \n \n 的查询可能会导致问题。我添加了以下几行:
\n\n Dim oXml As MSXML2.DOMDocument60\nRun Code Online (Sandbox Code Playgroud)\n\n结果也为 0。我期望是 3,因为概念有三个子项,即ConceptModel、Filter和Queries。所以,我更加疑惑了。
\n尽可能接近你的OP
我提请您注意几个错误或误解:
[1]无效的.LoadXML语法那么 .LoadXML ("C:\folder\folder\name.xml") 和 .Load ("C:\folder\folder\name.xml") 之间有什么区别?
Load需要一个文件路径,然后将文件内容加载到 oXML 对象中。
LoadXML不需要文件参数,但其实际XML 文本内容必须是格式良好的字符串。
[2]XML 区分大小写,因此节点需要通过其确切的文字名称来寻址:节点不会由"query"<Query>标识,"ConceptModel"与"conceptmodel"不同。作为第二个问题,我想问是否
Dim oXml As MSXML2.DOMDocument与相同Dim oXml As MSXML2.DOMDocument60, 因为我签入了工具/参考文献“Microsof XML,v6.0”?
不,不是。- 请注意,之前的声明将默认加载 3.0 版本。然而,绝对最好使用 6.0 版本(如今任何其他版本都已过时!)
当您使用所谓的早期绑定(引用“Microsoft XML,v6.0”)时,我将执行相同的操作,但引用的是当前版本 6.0:
Dim oXml As MSXML2.DOMDocument60 ' declare the xml doc object
Set oXml = New MSXML2.DOMDocument60 ' set an instance of it to memory
Run Code Online (Sandbox Code Playgroud)
[3]误解一些 XPath 表达式XPath 表达式中的起始斜杠“/”始终引用 DocumentElement(<Concepts>此处),您可以将.DocumentElement其添加到文档对象中。起始双斜杠“//xyz”将找到任何“xyz”节点(如果存在)。
例如
oXml.SelectNodes("//Query").Length
Run Code Online (Sandbox Code Playgroud)
返回与以下相同的 childNodes 编号(此处:3)
oXml.DocumentElement.SelectNodes("//Query").Length ' or
oXml.SelectSingleNode("//Queries").ChildNodes.Length ' or even
oXml.SelectNodes("/*/*/*/Query").Length`.
Run Code Online (Sandbox Code Playgroud)
参考 XML 版本 6.0 的代码示例
当然,您必须循环遍历多个 xml 文件,该示例仅使用一个(从第 2 行开始)。
针对xml 文件格式不正确的情况,我添加了详细的错误例程,使您能够识别假定的错误位置。Load两者LoadXML都返回一个布尔值(如果加载正确则返回 True,否则返回 False)。
Sub xmlTest()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets(3)
Dim oXml As MSXML2.DOMDocument60
Set oXml = New MSXML2.DOMDocument60
With oXml
.validateOnParse = True
.setProperty "SelectionLanguage", "XPath" ' necessary in version 3.0, possibly redundant here
.async = False
If Not .Load(ThisWorkbook.Path & "\xml\" & "name.xml") Then
Dim xPE As Object ' Set xPE = CreateObject("MSXML2.IXMLDOMParseError")
Dim strErrText As String
Set xPE = .parseError
With xPE
strErrText = "Load error " & .ErrorCode & " xml file " & vbCrLf & _
Replace(.URL, "file:///", "") & vbCrLf & vbCrLf & _
xPE.reason & _
"Source Text: " & .srcText & vbCrLf & vbCrLf & _
"Line No.: " & .Line & vbCrLf & _
"Line Pos.: " & .linepos & vbCrLf & _
"File Pos.: " & .filepos & vbCrLf & vbCrLf
End With
MsgBox strErrText, vbExclamation
Set xPE = Nothing
Exit Sub
End If
' Debug.Print "|" & oXml.XML & "|"
Dim Queries As IXMLDOMNodeList, Query As IXMLDOMNode
Dim Searched As String
Dim i&, ii&
i = 2 ' start row
' start XPath
Searched = "ConceptModel/Queries/Query" ' search string
Set Queries = oXml.DocumentElement.SelectNodes(Searched) ' XPath
'
ws.Cells(i, 1) = IIf(Queries.Length = 0, "No items", Queries.Length & " items")
ii = 1
For Each Query In Queries
ii = ii + 1
ws.Cells(i, ii) = Query.Text
Next
End With
End Sub
Run Code Online (Sandbox Code Playgroud)
附加提示
您可能还对如何通过 XMLDOM 列出所有子节点以及如何使用 VBA 从 XML 获取属性名称的示例感兴趣。
由于后来的评论,我添加了进一步的提示(感谢@barrowc)
“使用 MSXML v3.0 的另一个问题是默认选择语言是 XSLPatterns,而不是 XPath。有关 MSXML 版本之间的一些差异的详细信息请参见此处,并讨论 两种选择语言之间的差异。”
在当前的 MSXML2 版本 6.0 中,完全支持 XPath 1.0。看来XSL模式很早就被微软实现了,基本上可以看作是W3C标准化XPath之前XPath表达式的简化子集。
MSXML2 版本 3.0 至少允许通过显式选择语言设置来集成 XPath 1.0:
oXML.setProperty "SelectionLanguage", "XPath" ' oXML being the DOMDocument object as used in original post
Run Code Online (Sandbox Code Playgroud)