使用VBA从XML获取唯一属性

使用VBA从XML获取唯一属性,xml,vba,excel,dictionary,Xml,Vba,Excel,Dictionary,我有下面的XML。我需要从XML中获取唯一的属性和标记。有人能指导我从XML中获取唯一的属性吗?谢谢 <Elements> <Details> <Name>ABCD</Name> <Address>1D23ABC</Address> </Details> <Dept num = "12S3" > <Deptname>ITS</Deptname>

我有下面的XML。我需要从XML中获取唯一的属性和标记。有人能指导我从XML中获取唯一的属性吗?谢谢

<Elements>
<Details>
    <Name>ABCD</Name>
    <Address>1D23ABC</Address>
</Details>  
<Dept num = "12S3" >
    <Deptname>ITS</Deptname>
    <ID>A12S3</ID>
    <ID1>A12W3</ID1>
</Dept> 
    <Dept num = "123" >
    <Deptname>IT1</Deptname>
    <ID>A1231</ID>
    <ID1>A1213</ID1>
</Dept> 
下面是我正在使用的VBA代码:

设置mainnode=oXMLFile.SelectNodes//Elements 对于mainnode中的每个节点 将儿童视为对象 i=0 对于node.ChildNodes中的每个子节点 工作表Sheets1.Range C&i+1.Value=child.BaseName 以暗淡的儿童为对象 对于child.ChildNodes中的每个kiddo Debug.Print kiddo.BaseName 工作表Sheets1.i+1。值= kiddo.BaseName i=i+1 下一个孩子 下一个孩子 下一节点 电流输出:

Elements
Details    Name
           Address

Dept       Num
           Deptname
           ID
           ID1
Dept       Num
           Deptname
           ID
           ID1
第1版正则表达式: 通常不建议使用正则表达式来处理XML/HTML

选项显式 公共子测试 Dim xmlDoc作为新的MSXML2.DOMDocument60 设置xmlDoc=New MSXML2.DOMDocument60 加载C:\Users\User\Desktop\Test.xml Dim arr作为字符串,dict作为对象,key作为变量,i作为长 arr=SplitGetTagsxmlDoc.XML,:Set dict=CreateObjectScripting.Dictionary 对于i=LBoundarr到UBoundarr DICTREPLACEARRI,Chr$60,vbNullString,Chr$62,vbNullString=1 接下来我 ActiveSheet.RangeA1.Resizedict.Count,1=Application.WorksheetFunction.Transposedict.keys 端接头 公共函数GetTagsByVal xmlString作为字符串变量 Dim arr As String,i As Long,匹配As Object,re As Object Set re=CreateObjectVBScript.RegExp 带re .Global=True .MultiLine=True .IgnoreCase=False .模式= 如果.testxmlString 设置匹配项=.ExecutexmlString 将arr0重拨到匹配项。计数-1 对于i=LBoundarr到UBoundarr arri=matchesi 接下来我 其他的 arri=xmlString 如果结束 GetTags=Joinarr, 以 端函数 正则表达式

输出:

您可以删除/忽略覆盖文档类型的初始标记

参考资料:

工具>参考>Microsoft XML您的版本,例如6.0

第2版遍历树结构: 更健壮的解决方案,使您的现有代码能够使用字典字典,从而可以轻松写出树结构

Option Explicit
Public Sub testing()
    Dim xmlDoc As New MSXML2.DOMDocument60, mainNode As Object, Node As Object, dict As Object, r As Long
    Set xmlDoc = New MSXML2.DOMDocument60
    xmlDoc.Load "C:\Users\User\Desktop\Test.xml"
    Set mainNode = xmlDoc.SelectNodes("//Elements"): Set dict = CreateObject("Scripting.Dictionary")

    [B1] = xmlDoc.DocumentElement.nodeName

    For Each Node In mainNode
        Dim child As Object
        For Each child In Node.ChildNodes
            If Not dict.exists(child.BaseName) Then
                dict.Add child.BaseName, CreateObject("Scripting.Dictionary")
            End If
            Dim kiddo As Object
            For Each kiddo In child.ChildNodes
                If Not dict(child.BaseName).exists(kiddo.BaseName) Then
                    dict(child.BaseName).Add kiddo.BaseName, 1
                End If
            Next kiddo
        Next child
    Next Node
    r = 0
    Dim key1 As Variant, key2 As Variant
    For Each key1 In dict.keys
        Worksheets("sheet1").Range("C" & r + 1) = key1
        For Each key2 In dict(key1).keys
             Worksheets("sheet1").Range("D" & r + 1).Value = key2
             r = r + 1
        Next
    Next
End Sub

该XML示例中唯一的实际属性是num——您列出的所有其他属性都是元素tags@TimWilliams-我道歉。我需要上述XML中所有唯一的标记和属性。@QHarr-我只需要唯一的名称,而不考虑值。我不关心这些标记中的值是什么。你应该通过XSLT来获得它,这会更快、更有效。regex截图来自哪个工具?ThanksDept num=1253不是每个操作的预期输出的一部分,它应该是Dept和num,并用分隔符分隔。也不会在每个操作的树视图中输出。另外,值得注意的是,虽然这在这种特殊情况下可能会起作用,但使用RegEx解析XML/HTML/etc通常不被认为是最佳实践:@DavidZemens在最佳实践位中同意。一般来说,这是一种非常糟糕和不可靠的做法!关于它是否选择了正确的位:我认为OP的问题/评论有点混乱。我只需要不考虑值的唯一名称。我同意最新的评论。不管怎样,它们现在可能永远消失了:-@QHarr-谢谢你的密码。它适用于给定的sampel xml,但是当我为类似的其他xml运行代码时,我得到了“类型不匹配”。是否有理由找出哪个字段不匹配?我正在寻找一个树结构来识别父节点和子节点,并获得它们之间的唯一值。。如果有一种方法可以在不影响树结构的情况下识别唯一值,请告诉我。谢谢您:
Option Explicit
Public Sub testing()
    Dim xmlDoc As New MSXML2.DOMDocument60, mainNode As Object, Node As Object, dict As Object, r As Long
    Set xmlDoc = New MSXML2.DOMDocument60
    xmlDoc.Load "C:\Users\User\Desktop\Test.xml"
    Set mainNode = xmlDoc.SelectNodes("//Elements"): Set dict = CreateObject("Scripting.Dictionary")

    [B1] = xmlDoc.DocumentElement.nodeName

    For Each Node In mainNode
        Dim child As Object
        For Each child In Node.ChildNodes
            If Not dict.exists(child.BaseName) Then
                dict.Add child.BaseName, CreateObject("Scripting.Dictionary")
            End If
            Dim kiddo As Object
            For Each kiddo In child.ChildNodes
                If Not dict(child.BaseName).exists(kiddo.BaseName) Then
                    dict(child.BaseName).Add kiddo.BaseName, 1
                End If
            Next kiddo
        Next child
    Next Node
    r = 0
    Dim key1 As Variant, key2 As Variant
    For Each key1 In dict.keys
        Worksheets("sheet1").Range("C" & r + 1) = key1
        For Each key2 In dict(key1).keys
             Worksheets("sheet1").Range("D" & r + 1).Value = key2
             r = r + 1
        Next
    Next
End Sub