Comment puis-je copier en profondeur un élément de LINQ to XML?
-
03-07-2019 - |
Question
Je souhaite effectuer une copie complète d'un objet LINQ to XML XElement. La raison pour laquelle je veux faire cela est qu'il y a quelques nœuds dans le document pour lesquels je veux créer des copies modifiées (dans le même document). Je ne vois pas de méthode pour le faire.
Je pourrais convertir l'élément en une chaîne XML, puis le reparse, mais je me demande s'il existe un meilleur moyen.
La solution
Il n’est pas nécessaire de réparer. L'un des constructeurs de XElement prend un autre XElement et en fait une copie complète:
XElement original = new XElement("original");
XElement deepCopy = new XElement(original);
Voici quelques tests unitaires à démontrer:
[TestMethod]
public void XElementShallowCopyShouldOnlyCopyReference()
{
XElement original = new XElement("original");
XElement shallowCopy = original;
shallowCopy.Name = "copy";
Assert.AreEqual("copy", original.Name);
}
[TestMethod]
public void ShouldGetXElementDeepCopyUsingConstructorArgument()
{
XElement original = new XElement("original");
XElement deepCopy = new XElement(original);
deepCopy.Name = "copy";
Assert.AreEqual("original", original.Name);
Assert.AreEqual("copy", deepCopy.Name);
}
Autres conseils
Il semble que la meilleure méthode consiste à utiliser la méthode ToString and reparse. Voici le code:
XElement copy = XElement.Parse(original.ToString());
Levé directement à partir de C # 3.0 en bref :
Lorsqu'un noeud ou un attribut est ajouté à un élément (via une construction fonctionnelle ou une méthode Add), la propriété Parent du noeud ou de l'attribut est définie sur cet élément. Un nœud ne peut avoir qu'un seul élément parent: si vous ajoutez un nœud déjà parent à un second parent, le nœud est automatiquement cloné en profondeur. Dans l'exemple suivant, chaque client dispose d'une copie d'adresse distincte:
var address = new XElement ("address",
new XElement ("street", "Lawley St"),
new XElement ("town", "North Beach")
);
var customer1 = new XElement ("customer1", address);
var customer2 = new XElement ("customer2", address);
customer1.Element ("address").Element ("street").Value = "Another St";
Console.WriteLine (
customer2.Element ("address").Element ("street").Value); // Lawley St
Cette duplication automatique préserve l’instanciation d’objets X-DOM sans effets secondaires, ce qui est une autre caractéristique de la programmation fonctionnelle.
Cela devrait fonctionner:
var copy = new XElement(original.Name, original.Attributes(),
original.Elements() );
Je ne pense pas qu'il existe un mécanisme permettant de réaliser une copie complète d'une arborescence de styles XNode. Je pense qu'il vous reste deux options.
- Faites ce que vous avez suggéré de convertir en chaîne, puis de nouveau dans un arbre
- Ecrivez sur vous avec un motif visiteur
Le nombre de visiteurs est certes possible, mais il faudra beaucoup de travail et d’essais. Je pense que votre meilleure option est la première.