.net - obtener - ¿Cómo hago una copia profunda de un elemento en LINQ to XML?
manejo de xml en c# (5)
Quiero hacer una copia profunda de un LINQ to XML XElement. La razón por la que quiero hacer esto es que hay algunos nodos en el documento en los que quiero crear copias modificadas (en el mismo documento). No veo un método para hacer esto.
Podría convertir el elemento a una cadena XML y luego volver a analizarlo, pero me pregunto si hay una mejor manera.
Esto debería funcionar:
var copy = new XElement(original.Name, original.Attributes(),
original.Elements() );
Levantado directamente de C # 3.0 en una cáscara de nuez :
Cuando se agrega un nodo o atributo a un elemento (ya sea mediante la construcción funcional o un método Add), la propiedad Parent del atributo o nodo se establece en ese elemento. Un nodo puede tener solo un elemento principal: si agrega un nodo ya emparentado a un segundo elemento primario, el nodo se clonará de manera automática. En el siguiente ejemplo, cada cliente tiene una copia de dirección por separado:
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
Esta duplicación automática mantiene la instanciación de objetos X-DOM libre de efectos secundarios, otra característica distintiva de la programación funcional.
No creo que exista un mecanismo existente que le permita realizar una copia profunda de un árbol de estilo XNode. Creo que te quedan dos opciones.
- Haga lo que sugirió una conversión a una cadena y luego de vuelta a un árbol
- Escribe sobre ti mismo con un patrón de visitante
El patrón de visitante es ciertamente posible pero requerirá mucho trabajo y pruebas. Creo que tu mejor opción es # 1.
No hay necesidad de volver a rastrear. Uno de los constructores de XElement toma otro XElement y hace una copia profunda de él:
XElement original = new XElement("original");
XElement deepCopy = new XElement(original);
Aquí hay un par de pruebas unitarias para demostrar:
[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);
}
Parece que el método ToString y re-escaparse es la mejor manera. Aquí está el código:
XElement copy = XElement.Parse(original.ToString());