2008-10-16 7 views
49

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.¿Cómo hago una copia profunda de un elemento en LINQ to XML?

Podría convertir el elemento a una cadena XML y luego volver a analizarlo, pero me pregunto si hay una manera mejor.

+0

Daniel - Creo que debería reconsiderar la respuesta aceptada a esta pregunta. –

+0

Hecho- Cambié la respuesta aceptada. –

Respuesta

98

No hay necesidad de volver a analizar. Uno de los constructores de XElement toma otro XElement y hace una copia en profundidad de la misma:

XElement original = new XElement("original"); 
XElement deepCopy = new XElement(original); 

Aquí hay un par de pruebas de unidad 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); 
} 
+0

+1: * Esta * publicación debe ser la respuesta aceptada. –

+0

+1 para los métodos de prueba. –

+2

Creo que el constructor utilizado en este ejemplo se conoce genéricamente como ** Copy Constructor **. Aquí está el documento para el ['XElement' Copy Constructor] (http://msdn.microsoft.com/en-us/library/bb297950%28v=vs.110%29.aspx). También hay un ['XDocument' Copy Constructor] (http://msdn.microsoft.com/en-us/library/bb341301%28v=vs.110%29.aspx). Afortunadamente para nosotros, ** LINQ to XML ** lo hace fácil ... en general, [Deep Copying (o Cloning)] (http://stackoverflow.com/questions/78536/deep-cloning-objects-in-c -sharp) puede muchas veces no ser tan directo. – DavidRR

-2

No creo que haya un mecanismo existente que le permita realizar una copia profunda de un árbol de estilo XNode. Creo que te quedan dos opciones.

  1. Haz lo que sugiere un convertido en una cadena y luego de vuelta a un árbol
  2. Escribir en el mismo con un patrón de visitante

El patrón de visitante es ciertamente posible pero tomará un buen negocio de trabajo una prueba. Creo que tu mejor opción es # 1.

6

Parece que el método ToString y de reescalado es la mejor manera. Aquí está el código:

XElement copy = XElement.Parse(original.ToString()); 
+0

luego DstNode.Add (copiar) para agregarlo. Hecho. – Fraga

2

Lifted directamente de C# 3.0 in a Nutshell:

Cuando se añade un nodo o atributo a un elemento (ya sea a través de la construcción funcional o un método Add) el nodo o propiedad Parent de atributo 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 separada de dirección:

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 X-DOM objeto instanciación libre de efectos secundarios-otro sello distintivo de la programación funcional.

+3

¿Por qué está marcado como la respuesta aceptada? –

0

Esto debería funcionar:

var copy = new XElement(original.Name, original.Attributes(), 
         original.Elements()); 
Cuestiones relacionadas