2008-10-01 2 views
5

Ich muss den Inhalt eines Knotens in einer XElement-Hierarchie ersetzen, wenn der Elementname und alle Attributnamen und Werte einem Eingabeelement entsprechen . (Wenn es keine Übereinstimmung gibt, kann das neue Element hinzugefügt werden.)Ich brauche einen LINQ-Ausdruck, um ein XElement zu finden, wo der Elementname und die Attribute einem Eingabeknoten entsprechen.

Zum Beispiel, wenn meine Daten wie folgt aussehen:

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

Ich möchte das letzte Element zu finden, wenn ich eine Methode, mit diesem Aufruf Eingabe:

Die Methode sollte keine fest codierten Element- oder Attributnamen haben - sie stimmt einfach die Eingabe mit den Daten ab.

Antwort

5

Dies wird mit dem genauen Tag-Namen jedes gegebenes Element entspricht und Name/Wert-Paare Attribut:

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

Eine mögliche Optimierung (nicht sicher, wie die Daten intern gespeichert sind) den Namen als Argument für Elemente angeben, wäre() anstatt es in die Where-Klausel aufzunehmen. –

+0

Warum das gesamte Element ersetzen? Kannst du nicht nur den Wert ersetzen? – Haroon

+0

Ja, in diesem speziellen Fall könnten Sie einfach die Value-Eigenschaft festlegen. –

0

Sie können ein XPathSelectElement mit dem Pfad tun (zitieren Sie mich nicht, war in der Bar; wird im Morgen aufräumen)/root/thing2 [@ a1 = 'a' und @ a2 = 'b'] und dann .LastOrDefault() (XPathSelectElement ist eine Erweiterungsmethode in system.Linq.Xml).

Dadurch erhalten Sie den Knoten, den Sie ändern möchten. Ich bin mir nicht sicher, wie Sie es ändern wollen. Das Ergebnis, das Sie erhalten, ist das eigentliche XElement. Wenn Sie es ändern, ändert sich das Baumelement.