从xmlDoc中删除节点,如何删除父节点?

Posted

技术标签:

【中文标题】从xmlDoc中删除节点,如何删除父节点?【英文标题】:Remove node from xmlDoc, how to delete the parentNode? 【发布时间】:2012-08-10 11:15:16 【问题描述】:

我有一个 xmlDoc,这是其中的一部分:

<Main>
<Set>
    <MId>1</MId>
    <RName>
        <MetaData>
            <PrdctName>
                Test 1
            </PrdctName>
        </MetaData>
    </RName>
</Set>  
<Set>
    <MId>1</MId>
    <RName>
        <MetaData>
            <PrdctName>
                Test 2
            </PrdctName>
        </MetaData>
    </RName>
</Set>
<Set>
    <MId>1</MId>
    <RName>
        <MetaData>
            <PrdctName>
                Test 3
            </PrdctName>
        </MetaData>
    </RName>
</Set>
<Set>
    <MId>2</MId>
    <RName>
        <MetaData>
            <PrdctName>
                Test 1
            </PrdctName>
        </MetaData>
    </RName>
</Set>
</Main>

通过选择一个prdctName,必须从xmlDoc 中删除其余部分。例如,如果我选择“测试 1” 结果必须是:

<Main>
<Set>
    <MId>1</MId>
    <RName>
        <MetaData>
            <PrdctName>
                Test 1
            </PrdctName>
        </MetaData>
    </RName>
</Set>  
<Set>
    <MId>2</MId>
    <RName>
        <MetaData>
            <PrdctName>
                Test 1
            </PrdctName>
        </MetaData>
    </RName>
</Set>
</Main>

问题是我不知道如何删除标签。 所以删除后的 xml 现在看起来像:

<Main>
<Set>
    <MId>1</MId>
    <RName>
        <MetaData>
            <PrdctName>
                Test 1
            </PrdctName>
        </MetaData>
    </RName>
</Set>
<Set/>
<Set/>
<Set>
    <MId>2</MId>
    <RName>
        <MetaData>
            <PrdctName>
                Test 1
            </PrdctName>
        </MetaData>
    </RName>
</Set>
</Main>

我还必须编写哪些代码才能删除标签?

这是我现在使用的代码的一部分:

foreach (XmlNode chkNode in nodes)
                
            string currentName = "Test 1";
            if (!nameDict.ContainsKey(currentName))                                    
                    chkNode.ParentNode.RemoveAll();

【问题讨论】:

在您的最后一个 XML 示例中,我假设 &lt;/Set&gt;&lt;/Set&gt;&lt;/Set&gt; 的出现实际上应该是 &lt;/Set&gt;&lt;Set&gt;&lt;/Set&gt;? 当然必须有一个标签。有一次我在编辑这个问题,但在我保存问题后它就消失了。 No 是我得到的,这是正确的。第一个用于第一个 标签,另外两个来自已删除的节点。 &lt;/Set&gt;&lt;/Set&gt;&lt;/Set&gt; 永远不会正确,因为它不会产生有效的 XML。 对不起,这两个删除的节点当然必须是 【参考方案1】:

我认为您的问题是 XmlNode.RemoveAll() 仅删除节点的子节点,而 chkNode.ParentNode 属性正在选择带有 &lt;Set&gt; 标记的节点。因此,当您删除所有子节点时,您会留下一个空的 &lt;Set/&gt; 节点。您还需要能够删除该特定节点。

要调整现有方法,您需要执行以下操作:

foreach (XmlNode chkNode in nodes)
                
    string currentName = "Test 1";
    if (!nameDict.ContainsKey(currentName))
    
        XmlNode parent = chkNode.ParentNode;
        parent.ParentNode.RemoveChild(parent);
    

当然,我不能按原样测试这个,因为我不确定 nameDictnodes 到底是什么。

为了完整起见,如果 chkNodechkNode.ParentNode 是不能有父节点的 XmlNodes(例如 Attribute、Document、DocumentFragment、Entity、Notation 节点),则此代码将中断。如果您认为这是一种可能的情况,您可能希望包含适当的 null 检查或将此方法包装在 try-catch

类似:

XmlNode parent = chkNode.ParentNode;
if (parent != null && parent.ParentNode != null)
    parent.ParentNode.RemoveChild(parent);

或者:

try

    XmlNode parent = chkNode.ParentNode;
    parent.ParentNode.RemoveChild(parent);

catch (NullReferenceException ex)

    // do something with exception

LINQ 有几个选项可以更好地完成您想要的工作,但是由于您使用的是 C#2.0,因此该解决方案应该可以让您朝着正确的方向前进。

【讨论】:

nameDict 只是一个不需要删除名称的字典。节点是我选择的节点,所以在这个例子中所有的 节点。【参考方案2】:

这可以在 linq to xml 和 xpath 的帮助下完成。在下面找到示例:

    var xdocument = XDocument.Parse(xml)
    xdocument.Document.Root.Elements()
   .Where(element 
       => !element.XPathSelectElement("RName/MetaData/PrdctName").Value.Contains("Test 1"))
   .Remove();
   // saving results...
   xdocument.Save("somewhere.xml");

PS

不太好检查包含Value.Contains("Test 1")但这里看不到任何其他解决方案。

【讨论】:

【参考方案3】:

你可以这样尝试..

1) 读取标签并使用内部xml复制所有子节点。

2) 现在转到 MainParents 的根节点。

3) 现在将内部 xml 字符串替换为您在第一步中读取的 xml 字符串。

【讨论】:

以上是关于从xmlDoc中删除节点,如何删除父节点?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据子节点删除父节点和/或 css 样式

完成播放后,我是不是必须手动从父节点中删除发射器节点?

删除没有子节点的父节点

treeList如何删除一个叶子节点

检测节点何时被删除(或因为父节点被从 DOM 中删除)

原生js之删除节点(元素)