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

时间:2012-08-10 11:15:16

标签: c# xml c#-2.0

我有一个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();
}

3 个答案:

答案 0 :(得分:1)

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

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

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

当然,由于我不确定nameDictnodes究竟是什么,所以我无法对此进行测试。

为了完整起见,如果chkNodechkNode.ParentNodeXmlNodes且不能拥有父项(例如属性,文档,DocumentFragment,实体,表示法节点),则此代码将中断。如果您认为这是一种可能的情况,您可能希望包含适当的空值检查或将此方法包装在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,因此该解决方案可以帮助您找到正确的方向。

答案 1 :(得分:0)

可以在linq到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")不太好,但此处没有看到任何其他解决方案。

答案 2 :(得分:0)

您可以尝试这样。.

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

2)现在转到根节点MainParents。

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