【问题标题】:VBA XML parsing - looping through child nodesVBA XML 解析 - 遍历子节点
【发布时间】:2016-11-17 15:20:10
【问题描述】:

这是我第一次尝试使用 VBA 解析 XML 文件,所以我可能遗漏了明显的内容; 我已经可以打印了:

<values>
    <value code="1">A</value>
    <value code="2">B</value>
    <value code="3">C</value>
</values>

使用此代码行:

Debug.Print Variable.SelectSingleNode("values").XML

,其中values是其父节点Variable的子节点

但我不知道如何遍历values 的孩子,并打印“1A”、“2B”、“3C”对

据我了解,this question 使用根的第一个子节点,而我的目标是更深入地了解多级结构。

【问题讨论】:

标签: xml excel vba


【解决方案1】:

在这里,我们可以看到如何使用 MSXML6.0 库为您的特定示例解析 XML。要使用此示例,您需要在 VBA 项目中添加对 MSXML6.0 的引用。

我建议您特别注意 XPath 变量 '//value' 和诸如 .getNamedItem("code") 之类的选择器 --- 您需要熟悉其中的更多内容才能成为精通XML解析。幸运的是,其中很多都传递到了 HTML 解析中,所以这是一项有用的技能!

在这种情况下,我选择了所有值节点。遍历它们就像根据节点数组的长度进行 for 循环并使用 .item(i) 调用一样简单。

Option Explicit
Sub test()
    Dim strXml As String
    strXml = "<values><value code=""1"">A</value><value code=""2"">B</value><value code=""3"">C</value></values>"

    Dim objXML As MSXML2.DOMDocument60
    Set objXML = New MSXML2.DOMDocument60

    If Not objXML.LoadXML(strXml) Then  'strXML is the string with XML'
        Err.Raise objXML.parseError.ErrorCode, , objXML.parseError.reason
    End If

    Dim entry_point As IXMLDOMNode
    Set entry_point = objXML

    Dim myNodes As IXMLDOMNodeList
    Dim myElement As IXMLDOMElement
    Dim myNode As IXMLDOMNode
    Dim nNode As Integer
    Set myNodes = entry_point.SelectNodes("//value")
    If myNodes.Length > 0 Then
        For nNode = 0 To myNodes.Length
            Set myNode = myNodes(nNode) ' Get the first node.
            If myNode Is Nothing Then
            Else
                Debug.Print myNode.Text
                Debug.Print myNode.Attributes.getNamedItem("code").Text
            End If
        Next nNode
    Else
        Debug.Print "No nodes found."
    End If

End Sub

这是另一种情况,我选择所有 VALUES 节点,然后遍历每个 VALUES 节点的子节点(假设所有值节点都只有值子节点)。

Option Explicit
Sub test()
    Dim strXml As String
    strXml = "<values><value code=""1"">A</value><value code=""2"">B</value><value code=""3"">C</value></values>"

    Dim objXML As MSXML2.DOMDocument60
    Set objXML = New MSXML2.DOMDocument60

    If Not objXML.LoadXML(strXml) Then  'strXML is the string with XML'
        Err.Raise objXML.parseError.ErrorCode, , objXML.parseError.reason
    End If

    Dim entry_point As IXMLDOMNode
    Set entry_point = objXML

    Dim myNodes As IXMLDOMNodeList
    Dim myChildNodes As IXMLDOMNodeList
    Dim myElement As IXMLDOMElement
    Dim myNode As IXMLDOMNode
    Dim myChildNode As IXMLDOMNode
    Dim nNode As Integer
    Dim nChildNode As Integer
    Set myNodes = entry_point.SelectNodes("//values")
    If myNodes.Length > 0 Then
        For nNode = 0 To myNodes.Length - 1
            Set myNode = myNodes(nNode)
            If myNode Is Nothing Then
            Else
                Set myChildNodes = myNode.ChildNodes ' Get the children of the first node.
                For nChildNode = 0 To myChildNodes.Length - 1
                    Debug.Print myChildNodes(nChildNode).Text
                    Debug.Print myChildNodes(nChildNode).Attributes.getNamedItem("code").Text
                Next nChildNode
            End If
        Next nNode
    Else
        Debug.Print "No nodes found."
    End If

End Sub

【讨论】:

  • 如果我“按原样”运行您的代码,在声明 objXML 变量时会收到“未定义用户定义的类型”错误
  • 你添加了xml引用吗? O_o
  • 不,没有看到那个编辑:)。但是如果我添加它并与其他人共享代码,他们是否也需要自己添加它?不幸的是,这可能不是一个选择
  • 我通过声明所有变量 as Object 并设置 Set objXML = CreateObject("Microsoft.XMLDOM") 来避免添加引用
【解决方案2】:

使用 HTML 或 XML 元素的关键是使用 LocalsWatch 窗口来浏览元素的属性。子项目将位于 childNodechildrenitem 集合中。我还将在 Chrome 中打开文档,单击我的目标元素,并在适用时使用 Copy XPath。我可以让他们使用 XPath 来追踪我的目标元素。

在本例中,我将Stop 放在设置目标节点的行之后。接下来,我深入了解节点的属性(在 Immediate Window 中进行测试),直到找到我正在寻找的属性。

Sub TestStub()
    Const XMLTEST = "<values>" & _
          "<value code=""1"">A</value>" & _
          "<value code=""2"">B</value>" & _
          "<value code=""3"">C</value>" & _
          "</values>"
    Dim objXML As Object, node As Object

    Set objXML = CreateObject("MSXML2.DOMDocument")

    If Not objXML.LoadXML(XMLTEST) Then  'strXML is the string with XML'
        Err.Raise objXML.parseError.ErrorCode, , objXML.parseError.reason

    Else
        Set node = objXML.SelectSingleNode("values")
        Stop

    End If
End Sub

更新:如何使用 Immediate Window 测试循环遍历 childNodes 集合中的项目

【讨论】:

  • 虽然这并不能解决具体问题,但它概述了业余编码人员在处理问题中的 on 等情况时可以使用的极好程序
  • @horace_vr 无论好坏,这是我的意图。我应该继续创建循环,但 Cody G. 已经为您提供了正确答案。
  • @horace_vr 我继续并用For LoopFor each Loop 演示更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
相关资源
最近更新 更多