2012-08-10 205 views
0

我有一个xmlDoc中,这是它的一个部分:从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(); 
} 
+0

在你最后一个XML例子,我假设的''的次数实际上应该是''? – psubsee2003 2012-08-10 11:17:35

+0

当然必须有一个标签。当我编辑这个问题的时候,但是在我保存了这个问题之后它就消失了。 – Remco 2012-08-10 11:17:54

+0

否是我得到的,这是正确的。第一个是第一个标记,另外两个来自已删除的节点。 – Remco 2012-08-10 11:20:08

回答

0

我认为你的问题是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,实体,符号节点)。如果你认为这是一个可能的方案,您可能要包括适当的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,所以这个解决方案应该让你朝着正确的方向发展。

+0

nameDict只是一个名称不必被删除的词典。节点是我选择的节点,所以在本例中所有的节点都是。 – Remco 2012-08-10 11:46:15

+0

但我试过这个,这是解决方案。谢谢。 – Remco 2012-08-10 11:47:36

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")但在这里看不到任何其他的解决方案吧。