我需要解析数百个具有以下相同结构的XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<Concepts>
<ConceptModel name="food">
<Filters>
<Filter type="CC"/>
</Filters>
<Queries>
<Query lang="EN">(cheese, bread, wine)</Query>
<Query lang="DE">(Käse, Brot, Wein)</Query>
<Query lang="FR">(fromaige, pain, vin)</Query>
</Queries>
</ConceptModel>
</Concepts>
我已经阅读了以下互联网上的几篇文章和帖子,但无法提出解决方案:
到目前为止,我正在做
Dim oXml As MSXML2.DOMDocument
Set oXml = New MSXML2.DOMDocument
oXml.LoadXML ("C:\folder\folder\name.xml")
Dim Queries As IXMLDOMNodeList
Dim Query As IXMLDOMNode
ThisWorkbook.Sheets(3).Cells(i, 1) = "before loop"
Set Queries = oXml.SelectNodes("/concepts/Queries")
MsgBox "how many Queries " & Queries.Length
For Each Query In Queries
ThisWorkbook.Sheets(3).Cells(i, 1) = "Works"
ThisWorkbook.Sheets(3).Cells(i, 2) = Query.SelectNodes("Query").iTem(0).Text
i = i + 1
Next
VBA似乎可以理解此代码,但是它不读取内容。该循环没有被读取,这意味着(我猜)查询根本没有循环。 Msgbox "how many queries"
的结果为0可以证实这一点。但是实际上有三个查询。有人可以帮我吗?
第二个问题,我想问
Dim oXml As MSXML2.DOMDocument
将与
相同 Dim oXml As MSXML2.DOMDocument60
自从我签入工具/参考“ Microsof XML,v6.0”
我认为查询带有标签 可能会引起问题。我添加了以下行:
Dim childs As IXMLDOMNodeList
Set childs = oXml.SelectNodes("/concepts")
MsgBox "childs " & childs.Length
,其结果也为0。我希望3,因为概念有3个子级,即 ConceptModel,Filter 和 Queries 。所以,我更加困惑。
谢谢。
答案 0 :(得分:2)
尽可能靠近您的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
[3]
误解了某些XPath表达式 XPath表达式中的斜杠“ /”始终引用DocumentElement(此处为<Concepts>
),
您可以改为将.DocumentElement
添加到文档对象。起始双斜杠“ // xyz”将找到任何“ xyz”节点(如果存在)。
例如
oXml.SelectNodes("//Query").Length
返回与
相同的childNodes编号(此处:3) oXml.DocumentElement.SelectNodes("//Query").Length ' or
oXml.SelectSingleNode("//Queries").ChildNodes.Length ' or even
oXml.SelectNodes("/*/*/*/Query").Length`.
参考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
其他提示
您可能还对一个示例感兴趣,该示例如何通过XMLDOM列出所有子节点并obtain attribute names from XML using VBA。
由于稍后的评论(感谢@barrowc),我提供了进一步的提示
”使用MSXML v3.0的另一个问题是,默认选择语言是XSLPatterns而不是XPath。 有关MSXML版本之间的某些差异的详细信息为here here讨论了两种选择语言之间的差异。”
在当前的MSXML2版本6.0中,完全支持XPath 1.0。因此,似乎 XSL模式是Microsoft在较早的时候实现的,基本上可以将其视为XPath W3C标准化之前的XPath表达式的简化子集。
MSXML2版本3.0允许至少通过显式选择语言设置来集成XPath 1.0:
oXML.setProperty "SelectionLanguage", "XPath" ' oXML being the DOMDocument object as used in original post
答案 1 :(得分:1)
这是特殊字符(德语字母),这意味着您需要对XML文件执行批量替换之类的操作,因此开头不是这样:
<?xml version="1.0" encoding="UTF-8"?>
但这:
<?xml version="1.0" encoding="iso-8859-1" ?>
之后进行测试的代码:
Option Explicit
Public Sub test()
Dim xmlDoc As Object
Set xmlDoc = CreateObject("MSXML2.DOMDocument") 'New MSXML2.DOMDocument60
With xmlDoc
.validateOnParse = True
.setProperty "SelectionLanguage", "XPath"
.async = False
If Not .Load("C:\Users\User\Desktop\Test.xml") Then
Err.Raise .parseError.ErrorCode, , .parseError.reason
End If
End With
Debug.Print xmlDoc.SelectNodes("//Query").Length
End Sub
这是我正在使用的XML:
<?xml version="1.0" encoding="iso-8859-1" ?>
<Concepts>
<ConceptModel name="food">
<Filters>
<Filter type="CC"/>
</Filters>
<Queries>
<Query lang="EN">(cheese, bread, wine)</Query>
<Query lang="DE">(Käse, Brot, Wein)</Query>
<Query lang="FR">(fromaige, pain, vin)</Query>
</Queries>
</ConceptModel>
</Concepts>