循环遍历完整的 XML 文档

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14401193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 13:51:23  来源:igfitidea点击:

Loop through a full XML document

xmlvbams-accessrecursion

提问by dan

I'm looking for a way to loop through all the nodes of my XML document.

我正在寻找一种方法来遍历我的 XML 文档的所有节点。

XML file sample

XML 文件示例

<root>
    <llnode created="2005-05-24T15:26:24" createdby="42912153" createdbyname="" description="" id="107810306" modified="2008-06-05T16:07:44" name="" objname="" objtype="0" ownedby="42912153" ownedbyname="" parentid="107810295" size="4">
        <Nickname domain=""/>
        <MajorMinorContainer>false</MajorMinorContainer>
        <llnode created="2005-05-06T12:54:03" createdby="42912153" createdbyname="" description="" id="107815681" modified="2006-12-04T14:39:51" name="" objname="" objtype="0" ownedby="42912153" ownedbyname="" parentid="107810306" size="0">
            <Nickname domain=""/>
            <MajorMinorContainer>false</MajorMinorContainer>
        </llnode>
        <llnode created="2005-05-06T12:54:31" createdby="42912153" createdbyname="" description="" id="107815683" modified="2006-12-04T14:39:53" name="" objname="" objtype="0" ownedby="42912153" ownedbyname="" parentid="107810306" size="0">
            <Nickname domain=""/>
            <MajorMinorContainer>false</MajorMinorContainer>
        </llnode>
    </llnode>
    <llnode created="2005-05-24T15:26:24" createdby="42912153" createdbyname="" description="" id="107810306" modified="2008-06-05T16:07:44" name="" objname="" objtype="0" ownedby="42912153" ownedbyname="" parentid="107810295" size="4">
        <Nickname domain=""/>
        <MajorMinorContainer>false</MajorMinorContainer>
        <llnode created="2005-05-06T12:54:03" createdby="42912153" createdbyname="" description="" id="107815681" modified="2006-12-04T14:39:51" name="" objname="" objtype="0" ownedby="42912153" ownedbyname="" parentid="107810306" size="0">
            <Nickname domain=""/>
            <MajorMinorContainer>false</MajorMinorContainer>
        </llnode>
        <llnode created="2005-05-06T12:54:31" createdby="42912153" createdbyname="" description="" id="107815683" modified="2006-12-04T14:39:53" name="" objname="" objtype="0" ownedby="42912153" ownedbyname="" parentid="107810306" size="0">
            <Nickname domain=""/>
            <MajorMinorContainer>false</MajorMinorContainer>
        </llnode>
    </llnode>
</root>

The document always has the same structure. Each llnoderepresents a folder. This can go really deep (for the purpose of the above example, the scope is only 2, but it can go up to 10).

文档始终具有相同的结构。每个llnode代表一个文件夹。这可以非常深入(就上述示例而言,范围只有 2,但可以达到 10)。

How can I loop through all the records? I don't want to put a loop into a loop and then another loop and do this like 20 times to be sure to handle every node. Is there a way to just do a loop of loops?

如何遍历所有记录?我不想将一个循环放入一个循环然后再放入另一个循环并执行 20 次以确保处理每个节点。有没有办法只做一个循环?

Below is what I got so far, only working for the actual XML document (scope=2), would need to add as much loops as the scope increases (it shouldn't go over scope=10)

以下是我到目前为止所得到的,仅适用于实际的 XML 文档(范围 = 2),需要随着范围的增加添加尽可能多的循环(它不应该超过范围 = 10)

Original VBA(from original question)

原始 VBA(来自原始问题)

xmlExportDoc = "myXmlDoc.xml"

Set xmlDoc = New MSXML2.DOMDocument
xmlDoc.Load (xmlExportDoc)

Set xmlNodeList = xmlDoc.SelectNodes("//llnode")

For Each Node In xmlNodeList
   MsgBox "Listing the EXISTING nodes"
   MsgBox Node.nodeName & " " & Node.NodeValue & " " & Node.NodeType

   If Node.HasChildNodes() Then
      MsgBox Node.nodeName & "has child nodes"
      Set xmlNodeList2 = Node.ChildNodes

      For Each Node2 In oNodeList2
          MsgBox Node2.nodeName & " " & Node2.NodeValue & " " & Node2.NodeType

          If Node2.HasChildNodes() Then
             MsgBox Node2.nodeName & "has child nodes"
          End If
      Next
   End If
Next

UPDATED VBA

更新的 VBA

Private Function xmlParse(n As MSXML2.IXMLDOMNode)
    Dim n2 As MSXML2.IXMLDOMNode
    MsgBox n.nodeName & " " & n.NodeValue & " " & n.NodeType

    If n.HasChildNodes() Then
        MsgBox n.nodeName & " has child nodes"

        For Each n2 In n.ChildNodes
            xmlParse (n2)
        Next

        MsgBox "Done listing child nodes for " & n.nodeName
    End If
End Function

And the code of the event:

以及事件的代码:

    Dim xmlExportDoc As String
    Dim xmlDoc As MSXML2.DOMDocument
    Dim xmlNodeList As MSXML2.IXMLDOMNodeList, xmlNodeList2
    Dim Node As MSXML2.IXMLDOMNode

    xmlExportDoc = "http://myserver.com/myDoc.xml"

    Set xmlDoc = New MSXML2.DOMDocument
    xmlDoc.async = False
    xmlDoc.Load (xmlExportDoc)

    Set xmlNodeList = xmlDoc.SelectNodes("//llnode")

    For Each Node In xmlNodeList
        Call xmlParse(Node)
    Next

This still don't work, got an error when doing the recursive xmlParse()call because MSXML2.IXMLDOMNode.ChildNodesdoesn't seem to be a MSXML2.IXMLDOMNodetype.

这仍然不起作用,在进行递归xmlParse()调用时出错,因为MSXML2.IXMLDOMNode.ChildNodes它似乎不是一种MSXML2.IXMLDOMNode类型。

回答by JLRishe

I think what you need here is a recursive function. I don't really know VBA syntax so forgive the pseudocode, but you should be able to do something like this:

我认为你在这里需要的是一个递归函数。我真的不知道 VBA 语法所以原谅伪代码,但你应该能够做这样的事情:

Set xmlNodeList = xmlDoc.SelectNodes("/*/llnode")
For Each node in xmlNodeList
    ListNodes(node)
Next

Function ListNodes(n As Node) 
     MsgBox n.nodeName & " " & n.NodeValue & " " n.NodeType
     If n.HasChildNodes() Then
        MsgBox n.nodeName & "has child nodes"
        For Each n2 in n.ChildNodes
           ListNodes(n2)
        Next
        MsgBox "Done listing child nodes for " & n.nodeName
     End If   
End Function

回答by dan

Here's what I come with so far:

这是我到目前为止的内容:

xmlExportDoc = "http://www.mysite.com/myDoc.xml"

Dim xmldoc As MSXML2.DOMDocument
Dim xmlNode As MSXML2.IXMLDOMNode
Dim xmlNodeList As MSXML2.IXMLDOMNodeList
Dim myNode As MSXML2.IXMLDOMNode

Set xmldoc = New MSXML2.DOMDocument
xmldoc.async = False
xmldoc.Load (xmlExportDoc)
Set xmlNodeList = xmldoc.getElementsByTagName("*")
On Error Resume Next
For Each xmlNode In xmlNodeList
    For Each myNode In xmlNode.ChildNodes
        'Debug.Print xmlNode.Attributes(0).Text
    Next myNode
Next xmlNode
Set xmldoc = Nothing

It works if the hierarchy isn't important, because this script just loops through the nodes whatever level it is. If hierarchy is important, look at JLRishe's answer.

如果层次结构不重要,它就可以工作,因为该脚本只是循环遍历节点,无论它是什么级别。如果层次结构很重要,请查看 JLRishe 的答案。