2012-08-10 258 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")但在這裏看不到任何其他的解決方案吧。