【问题标题】:Remove (child) node from XML DOM object using VBA (Excel)使用 VBA (Excel) 从 XML DOM 对象中删除(子)节点
【发布时间】:2020-06-26 09:12:06
【问题描述】:

我正在使用模板创建相当复杂的 XML 文件,用可以在 Excel 工作表中输入的值替换特殊的搜索字符串,然后存储 xml 文件。

 Dim strInpPath As String
 Dim strOutpPath As String
 
 Dim fso
 Dim f
 Dim oDomRd As Object, oNode As Object, i As Long, oAtt As Object, oGroup As Object, oDomWr As Object
 Dim oTest As Object
 
 
 strInpPath = ActiveWorkbook.ActiveSheet.Cells(3, 4).Value
 strOutputPath = ActiveWorkbook.ActiveSheet.Cells(4, 4).Value
 

 Set oDomRd = CreateObject("MSXML2.DOMDocument")
 oDomRd.Load strInpPath
 Set oDomWr = CreateObject("MSXML2.DOMDocument")
 
 Set fso = CreateObject("Scripting.FileSystemObject")
 Set f = fso.OpenTextFile(strOutputPath, 2, True)

 Set oGroup = oDomRd.SelectNodes("/")
 Set oNode = oGroup.NextNode
 If Not (oNode Is Nothing) Then
    strout = oNode.XML
    strout = ScanTable("_S_AND_R_TABLE_1", strout)
    oDomRd.LoadXML (strout)
    Set oGroup = oDomRd.SelectNodes("/")
    Set oNode = oGroup.NextNode
    
    If oNode.HasChildNodes() Then
        Set oLists = oNode.DocumentElement
        Run RemoveOptionalEmptyTags(oLists)
    End If
    strout = oNode.XML
    f.write (strout)
 Else
     strout = "001 error reading file"
 End If
 MsgBox strout
 
End Function

某些字段值不是强制性的,因此可以留空。在这种情况下,第一个过程(scantable)输入“##REMOVE##”作为值。在第二步中,我想遍历整个 DOMObject 并删除具有值“##REMOVE##”的节点

对于这第二步,我创建了一个程序:

Public Function RemoveOptionalEmptyTags(ByRef oLists)

    For Each listnode In oLists.ChildNodes
        If listnode.HasChildNodes() Then
            Run RemoveOptionalEmptyTags(listnode) 
        Else
            lcBasename = listnode.ParentNode.BaseName
            lcText = listnode.Text
            If lcText = "##REMOVE##" Then
                listnode.ParentNode.RemoveChild listnode
                Exit For
            End If
        End If
    Next listnode

End Function

这很好用,唯一的问题是,节点没有删除,它只是空的():

    <Cdtr>
        <Nm>Name Creditor</Nm>
        <PstlAdr>
            <Ctry>DE</Ctry>
            <AdrLine>Street</AdrLine>
            <AdrLine/>
        </PstlAdr>
    </Cdtr>

现在的问题是: 我怎样才能完全删除节点,所以它看起来像这样(第二个消失了):

    <Cdtr>
        <Nm>Name Creditor</Nm>
        <PstlAdr>
            <Ctry>DE</Ctry>
            <AdrLine>Street</AdrLine>
        </PstlAdr>
    </Cdtr>

【问题讨论】:

  • oLists如何设置(请在OP中编辑XPath或显示更完整的代码)?应该是NodeList 而不是单个节点。节点列表无法显示 .ChildNodes 并且递归调用使用带有 both 类型的参数 oLists,这应该是典型的不匹配。所以我怀疑你的功能是否有效。 ...并删除删除代码行中... (listnode) 周围的括号:listnode.ParentNode.RemoveChild listnode
  • @T.M.谢谢你的评论。我希望我添加的代码确实使它更清晰一些。我删除了(listnode)周围的括号,不幸的是代码的行为没有改变,'removed'标签只是空的,没有被删除...... :-(
  • 发布了您的问题的答案;请随意勾选绿色复选标记和/或投票来接受:-)

标签: excel xml vba removechild


【解决方案1】:

基本上RemoveChild 语法是正确的:

{NodeToDelete}.ParentNode.RemoveChild {NodeToDelete}

但让我们重复 xml 结构并注意每个文本节点(如果存在)被视为其父节点的子节点(即更深一层)。

<Cdtr>                                   <!-- 0 documentElement                      -->
    <Nm>Name Creditor</Nm>               <!-- 1 ChildNode of Nm = 'Name Creditor'    -->
    <PstlAdr>                            <!-- 1 listNode.ParentNode.ParentNode       -->
        <Ctry>DE</Ctry>                  <!--   2 ChildNode of Ctry = 'DE'           -->
        <AdrLine>Street</AdrLine>        <!--   2 ChildNode of AdrLine[1] = 'Street' -->                   
        <AdrLine>                        <!--   2 listNode.ParentNode to be removed  -->
            <!-- NODETEXT ##REMOVE## --> <!--     3 ChildNode of AdrLine[2]          -->
        </AdrLine>
        </PstlAdr>
</Cdtr>

通过

在 xml 层次结构中下探到底部(假设文本值)
    listnode.ParentNode.RemoveChild listnode

您正在删除 AdrLine[2](级别 3)的文本 ChildNode,即字符串 "##REMOVE##", 但不是容器节点AdrLine[2](2 级)。因此,您只删除了虚拟文本。

按照函数RemoveOptionalEmptyTags() 中的逻辑,您必须尽可能地编写代码:

    listNode.ParentNode.ParentNode.RemoveChild listNode.ParentNode

寻址PstlAdr(=级别1)执行删除其子节点AdrLine[2](即在级别2) 自动包括在级别 3 删除虚拟字符串“##REMOVE”。

相关链接

XML Parse via VBA

Obtain atrribute names from xml using VBA

【讨论】:

  • 非常感谢您的帮助。看起来它工作得很好。我还需要做一些测试,但第一次测试非常成功。
  • @Dietmar 你写的“看起来它工作得很完美。我仍然需要做一些测试......”。如果你能完成测试,请允许我提问。 - 如果我的帖子解决了您的问题,请勾选绿色复选标记随时接受;如果有帮助请点赞:-)
猜你喜欢
  • 1970-01-01
  • 2014-09-13
  • 2021-05-30
  • 2011-11-04
  • 2023-03-29
  • 1970-01-01
  • 2015-03-26
  • 1970-01-01
  • 2011-02-09
相关资源
最近更新 更多