2008-10-01 2 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, поэтому его изменение изменит элемент дерева.

 Смежные вопросы

  • Нет связанных вопросов^_^