Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I need a LINQ expression to find an XElement where the element name and attributes match an input node

Tags:

I need to replace the contents of a node in an XElement hierarchy when the element name and all the attribute names and values match an input element. (If there is no match, the new element can be added.)

For example, if my data looks like this:

<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>

I want to find the last element when I call a method with this input:

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

The method should have no hard-coded element or attribute names - it simply matches the input to the data.

like image 780
Wonko Avatar asked Oct 01 '08 00:10

Wonko


1 Answers

This will match any given element with exact tag name and attribute name/value pairs:

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);
like image 90
Mark Cidade Avatar answered Nov 02 '22 22:11

Mark Cidade