2008-10-01 54 views
5

當元素名稱和所有屬性名稱和值匹配輸入元素時,我需要替換XElement層次結構中節點的內容。 (如果沒有匹配,可以添加新的元素。)我需要一個LINQ表達式來查找元素名稱和屬性與輸入節點匹配的XElement

例如,如果我的數據是這樣的:

<root> 
    <thing1 a1="a" a2="b">one</thing1> 
    <thing2 a1="a" a2="a">two</thing2> 
    <thing2 a1="a" a3="b">three</thing2> 
    <thing2 a1="a">four</thing2> 
    <thing2 a1="a" a2="b">five</thing2> 
<root> 

我想找到的最後一個元素,當我把這個方法輸入:

<thing2 a1="a" a2="b">new value</thing2> 

該方法應該沒有硬編碼的元素或屬性名稱 - 它只是將輸入與數據匹配。

回答

5

這將匹配確切標籤名稱的任何給定的元素和屬性名稱/值對:

public static void ReplaceOrAdd(this XElement source, XElement node) 
{ var q = from x in source.Elements() 
      where x.Name == node.Name 
       && x.Attributes().All 
            (a =>node.Attributes().Any 
            (b =>a.Name==b.Name && a.Value==b.Value)) 
      select x; 

    var n = q.LastOrDefault(); 

    if (n == null) source.Add(node); 
    else n.ReplaceWith(node);            
} 

var root =XElement.Parse(data); 
var newElem=XElement.Parse("<thing2 a1=\"a\" a2=\"b\">new value</thing2>"); 

root.ReplaceOrAdd(newElem); 
+0

一個潛在的優化(不知道數據如何在內部存儲)將指定的名稱作爲參數傳遞給元素()而不是將其包含在Where子句中。 – 2008-10-01 05:24:27

0

你可以用路徑做一個XPathSelectElement(不要引用我,去過吧,清理乾淨)/ root/thing2 [@ a1 ='a'和@ a2 ='b']然後執行.LastOrDefault()(XPathSelectElement是system.Linq.Xml中的擴展方法)。

這將爲您帶來您想要更改的節點。不過,我不確定你想如何改變它。你得到的結果是實際的XElement,所以改變它會改變樹元素。

相關問題