2008-10-01 21 views
5

Je dois remplacer le contenu d'un noeud dans une hiérarchie XElement lorsque le nom de l'élément et tous les noms et valeurs d'attribut correspondent à un élément d'entrée . (S'il n'y a pas de correspondance, le nouvel élément peut être ajouté.)J'ai besoin d'une expression LINQ pour trouver un XElement où le nom et les attributs de l'élément correspondent à un noeud d'entrée

Par exemple, si mes données ressemble à ceci:

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

Je veux trouver le dernier élément quand je l'appelle une méthode avec cette entrée:

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

la méthode ne devrait avoir aucun élément codé en dur ou des noms d'attributs - il correspond simplement l'entrée des données.

Répondre

5

Cela correspond à tout élément donné avec le nom de l'étiquette exacte et attribut paires nom/valeur:

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

Une optimisation possible (pas sûr de la façon dont les données sont stockées en interne) serait de préciser le nom comme argument aux éléments() au lieu de l'inclure dans la clause Where. –

+0

Pourquoi remplacer l'élément entier? Ne pouvez-vous pas simplement remplacer la valeur seulement? – Haroon

+0

Oui, dans ce cas particulier, vous pouvez simplement définir la propriété 'Value'. –

0

Vous pouvez faire un XPathSelectElement avec le chemin (ne pas citer moi, été à la barre, nettoiera le matin)/root/thing2 [@ a1 = 'a' et @ a2 = 'b'] puis prenez .LastOrDefault() (XPathSelectElement est une méthode d'extension dans system.Linq.Xml).

Vous obtiendrez ainsi le noeud que vous souhaitez modifier. Cependant, je ne suis pas sûr de la façon dont vous voulez le changer. Le résultat que vous obtenez est le XElement réel, donc le changer va changer l'élément de l'arbre.