是否可以跳过Excel VBA中XML文件中的节点?

时间:2017-07-27 06:03:18

标签: xml excel vba excel-vba xml-parsing

我对所有这些XML和VBA都很陌生。我老老实实地根据我对oop的了解做了一切,但我正在进行的当前项目需要在VBA中完成。
我到处搜索,但我无法找到并且无法想出任何实际的方法来做我现在必须做的事情,所以我要求所有人在这里寻求帮助如果可能的话。

所以基本上我有一个类似这样的XML文件:

<a name="something" >
   <b name="something">
      <c>
         <d>number1</d>
         <e>number2</e>
         <f>
            <g>number3</g>
            <h>number4</h>
         </f>
       </c>
    </b>
</a>

我的问题是我需要在Excel工作表中生成XML的内容。我知道怎么做,但是,我最终得到的是:

  

东西
  东西
   number1 number2 number3 number4
  NUMBER1
  数字2
   number3 number4
  number3的
  number4

我想要的是以某种方式摆脱斜体字。

我在子程序中使用递归,因为它是如何需要的。但是,当我检查子节点和要打印的节点值时,我最终会得到所有子节点及其自身没有特定值的节点的值。

我知道我可以使用baseName手动跳过节点,但这不是我正在寻找的。如果可以使用它自己的功能或可能适用于任何此类情况的更通用的功能,那就太好了。

感谢您的帮助!

编辑:(我现在的代码)

Sub Main()
    Dim XDoc As MSXML2.DOMDocument
    Set XDoc = New MSXML2.DOMDocument

    Set mainWorkBook = ActiveWorkbook
    mainWorkBook.Sheets("Sheet1").Clear

    Dim point As IXMLDOMSelection

    Filename = ThisWorkbook.Worksheets("Sheet1").Range("A1").Value
    XDoc.Load (Filename)

    Set point = XDoc.SelectNodes("/*")
    Call ProcessChildNodes(point(0))
End Sub


Sub PrintNodeValue(Node As IXMLDOMNode)
    If (Node.Attributes.Length = 0) Then
        Row = Row + 1
        mainWorkBook.Sheets("Sheet1").Cells(Row, 1).Value = Node.Text
    End If
End Sub


Sub PrintAttributesValue(Node As IXMLDOMNode)
    If (Node.Attributes.Length <> 0) Then
        Row = Row + 1
        For j = Node.Attributes.Length - 1 To 0 Step -1
            strng = Node.Attributes.Length
            mainWorkBook.Sheets("Sheet1").Cells(Row, strng - j).Value = Node.Attributes(j).Text
        Next
    End If
End Sub


Sub ProcessChildNodes(Node As IXMLDOMNode) 
    If (Node.HasChildNodes) Then
        For m = 0 To Node.ChildNodes.Length - 1
            If Node.ChildNodes(m).NodeType <> NODE_TEXT Then
                Call PrintNodeValue(Node.ChildNodes(m))
                Call PrintAttributesValue(Node.ChildNodes(m))
                Call ProcessChildNodes(Node.ChildNodes(m))
            End If
        Next
    Else
    End If
End Sub

1 个答案:

答案 0 :(得分:1)

如果我理解正确,你想忽略具有

的节点
  • 没有文字输入
  • 且没有属性
您的示例<c><f>中的

我发现的唯一技巧是直接处理XML。 因此,我们首先搜索只有节点<c><f>但没有其他节点的唯一参数。因此我发现了这个规则:

  1. 节点不得具有属性
  2. 该节点必须直接跟随另一个节点(无文本)
  3. 这意味着在<c><f>之后,会有另一个以<开头的标记。

    理论

    1. 如果我们看一下<c>获得的节点Node.xml的XML代码,它看起来像:

      <c>
          <d>number1</d>
          <e>number2</e>
          <f>
              <g>number3</g>
              <h>number4</h>
          </f>
      </c>
      
    2. 为了便于处理,我们将换行符,制表符和空格展平,所以我们最终在这里:

      <c><d>number1</d><e>number2</e><f><g>number3</g><h>number4</h></f></c>
      
    3. 现在我们只需要检查第一个节点标记<c>是否直接,然后是另一个以<开头的标记。因此,我们找到第一个>并查看它是否后跟<。如果这是真的,那么节点可以省略,因为它没有属性也没有文本。

    4. 让我们开始编码

      1. 我们在PrintNodeValue过程中执行所有操作,然后开始声明变量并获取实际处理的节点的原始XML代码:

        Dim xml as String
        xml = Node.xml
        
      2. 我们将xml展平并删除所有换行符,制表符和空格

        xml = Replace(xml, vbCrLf, vbNullString)
        xml = Replace(xml, vbTab, vbNullString)
        xml = Replace(xml, " ", vbNullString)
        

        xml现在是<c><d>number1</d><e>number2</e><f><g>number3</g><h>number4</h></f></c>

      3. 我们删除了第一个标记

        xml = Right(xml, Len(xml) - InStr(1, xml, ">"))
        

        并查看我们的2条规则(没有属性,后面跟着另一个标签直接适用)

        If (Node.Attributes.Length = 0) And Left(xml, 1) <> "<" Then
        
      4. 所以我们最终......

        Sub PrintNodeValue(Node As IXMLDOMNode)
            Dim xml As String
            xml = Node.xml                                  'get raw xml
            xml = Replace(xml, vbCrLf, vbNullString)        'strip off line breaks
            xml = Replace(xml, vbTab, vbNullString)         'strip off tabs
            xml = Replace(xml, " ", vbNullString)           'strip off spaces
            xml = Right(xml, Len(xml) - InStr(1, xml, ">")) 'strip off first tag
        
            If (Node.Attributes.Length = 0) And Left(xml, 1) <> "<" Then 'check our 2 rules
                iRow = iRow + 1
                mainWorkBook.Sheets("Sheet1").Cells(iRow, 1).Value = Node.Text
            End If
        End Sub
        

        产生......

          

        东西
          东西
          NUMBER1
          数字2
          number3的
          number4

        请注意,您可能需要将vbCrLf更改为vbCrvbLf,具体取决于哪个系统,例如。 Windows,Linux或Mac XML文件最初来自(它们使用不同的换行符)。为了安全起见,您还可以删除所有3。

        xml = Replace(xml, vbCrLf, vbNullString)
        xml = Replace(xml, vbCr, vbNullString)
        xml = Replace(xml, vbLf, vbNullString)