2012-11-10 42 views
-1

我有這樣的XML:C#中的LINQ to XML - 提取子元素的父母

<Root> 
    <RootKey>1</RootKey> 
    <ChildL1> 
    <ChildL1Key>12</ChildL1Key> 
    <Child2> 
     <Child2Key>TakeMe</Child2Key> 
    </Child2> 
    <Child2> 
     <Child2Key>365</Child2Key> 
    </Child2> 
    </ChildL1> 
    <ChildL1> 
    <ChildL1Key>95</ChildL1Key> 
    <Child2> 
     <Child2Key>958</Child2Key> 
    </Child2> 
    <Child2> 
     <Child2Key>574</Child2Key> 
    </Child2> 
    </ChildL1> 
</Root> 

我需要提取CHILD2其中Child2Key == 「TakeMe」 的父母。結果將是:

<Root> 
    <RootKey>1</RootKey> 
    <ChildL1> 
    <ChildL1Key>12</ChildL1Key> 
    <Child2> 
     <Child2Key>TakeMe</Child2Key> 
    </Child2> 
    </ChildL1> 
</Root> 

我可以做2個步驟。從Child2向上遍歷父進程並獲取它們的密鑰,並在下一步中使用其他密鑰刪除這些元素。如果可能,我寧願在一個查詢中執行。

+1

爲什麼會'ChildL1Key'元素包括在內,而'RootKey'元素?那些不是'Child2Key'的直接祖先。 –

+1

因爲他們是Child2的父母的一部分,正如我所說我需要提取。感謝投票。 – Yoav

+0

@Yoav你需要xml作爲輸出,或只是數據? –

回答

0
XDocument xdoc = XDocument.Load(path_to_xml); 
xdoc.Descendants("Child2") 
    .Where(c2 => c2.Element("Child2Key").Value != "TakeMe") 
    .Remove(); 

xdoc.Descendants("ChildL1") 
    .Where(c1 => !c1.Descendants("Child2").Any()) 
    .Remove(); 

// now xdoc contains what you need 
string xml = xdoc.ToString(); 

第一個查詢將刪除與搜索條件不匹配的所有Child2節點。

第二個查詢將刪除所有ChildL1,這些節點不再有Child2節點。

特供LB

xdoc.Descendants("ChildL1")    
    .Where(c1 => !c1.Descendants("Child2") 
        .Any(c2 => c2.Element("Child2Key").Value == "TakeMe")) 
    .Concat(xdoc.Descendants("Child2") 
       .Where(c2 => c2.Element("Child2Key").Value != "TakeMe")) 
    .Remove(); 
+0

'我可以分兩步完成。 .......我寧願做一個查詢,如果可能的話。' –

+0

仔細閱讀問題:我可以**可能**分兩步進行。 **從Child2向上遍歷父進程並獲取它們的密鑰,然後在下一步中使用其他密鑰**移除元素。如果可能,我寧願在一個查詢中執行。 - 我一開始就這樣做。它也不是完整的解決方案。 OP需要第三步移除ChildL1節點。此外,這項任務無法在一個步驟中完成(如果可能的話) –

+0

不需要粗魯,你只需一步? –