Necesito una expresión LINQ para encontrar un XElement donde el nombre del elemento y los atributos coincidan con un nodo de entrada

StackOverflow https://stackoverflow.com/questions/155685

Pregunta

Necesito reemplazar el contenido de un nodo en una jerarquía de XElement cuando el nombre del elemento y todos los nombres y valores de atributo coinciden con un elemento de entrada. (Si no hay coincidencia, se puede agregar el nuevo elemento).

Por ejemplo, si mis datos se ven así:

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

Quiero encontrar el último elemento cuando llamo a un método con esta entrada:

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

El método no debe tener ningún elemento de código o nombre de atributo, simplemente hace coincidir la entrada con los datos.

¿Fue útil?

Solución

Esto hará coincidir cualquier elemento dado con pares de nombre de etiqueta y nombre / valor de atributo exactos:

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

Otros consejos

Puedes hacer un XPathSelectElement con la ruta (no me cites, he estado en la barra; limpiaré por la mañana) / root / thing2 [@ a1 = 'a' and @ a2 = 'b'] y luego tome .LastOrDefault () (XPathSelectElement es un método de extensión en system.Linq.Xml).

Eso te dará el nodo que deseas cambiar. Sin embargo, no estoy seguro de cómo quieres cambiarlo. El resultado que obtienes es el XElement real, por lo que cambiarlo cambiará el elemento del árbol.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top