Creación de árboles XML en C# (LINQ to XML)

En este artículo se proporciona información sobre la creación de árboles XML en C#.

Para obtener información sobre el uso de los resultados de las consultas LINQ como contenido de XElement, vea Construcción funcional.

Construcción de elementos

Las firmas de los constructores XElement y XAttribute le permiten pasar los contenidos del elemento o atributo como argumentos del constructor. Dado que uno de los constructores recibe un número variable de argumentos, podrá pasar tantos elementos secundarios como desee. Por supuesto, cada uno de esos elementos secundarios podrá contener sus propios elementos secundarios. Para cualquier elemento, podrá agregar cuantos atributos desee.

Cuando se agregan objetos XNode (incluyendo el objeto XElement) o XAttribute, si el contenido nuevo no tiene un elemento primario, los objetos simplemente se adjuntan al árbol XML. Si el contenido nuevo ya tiene un elemento primario y forma parte de otro árbol XML, el nuevo contenido se clonará y ese clon se asociará al árbol XML. El último ejemplo de este artículo muestra esto.

Para crear un contactsXElement, podría utilizar el siguiente código:

XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"),
            new XElement("Phone", "206-555-0144"),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );

Si se aplica correctamente la sangría, el código que construye los objetos XElement se asemeja mucho a la estructura del contenido XML subyacente.

Constructores de XElement

La clase XElement utiliza los siguientes constructores para llevar a cabo una construcción funcional. Observe que existen algunos otros constructores para XElement, pero, dado que no se usan en la construcción funcional, no se indican aquí.

Constructor Descripción
XElement(XName name, object content) Crea una interfaz XElement. El parámetro name especifica el nombre del elemento; content especifica el contenido del elemento.
XElement(XName name) Crea un XElement cuyo XName se inicializa con el nombre especificado.
XElement(XName name, params object[] content) Crea un XElement cuyo XName se inicializa con el nombre especificado. Los atributos y/o elementos secundarios se crean a partir de los contenidos de la lista de parámetros.

El parámetro content es extremadamente flexible. Admite cualquier tipo de objeto que sea un elemento secundario válido de XElement. Se aplicarán las siguientes reglas a los diferentes tipos de objetos pasados en este parámetros:

  • Una cadena se agrega como contenido de tipo texto.
  • Un XElement se agrega como un elemento secundario.
  • Un XAttribute se agrega como un atributo.
  • Un XProcessingInstruction, XComment o un XText se agregan como un contenido secundario.
  • Un IEnumerable es un tipo enumerado y se aplicarán estas reglas recursivamente a los resultados.
  • Para el resto de tipos, se llamará a su método ToString y se agregará el resultado como contenido de tipo texto.

Ejemplo: Creación de XElement con contenido

Puede crear un XElement que contenga un contenido simple con una única llamada a método. Para ello, especifique el contenido como segundo parámetro, tal y como sigue:

XElement n = new XElement("Customer", "Adventure Works");
Console.WriteLine(n);

Este ejemplo produce el siguiente resultado:

<Customer>Adventure Works</Customer>

Puede pasar cualquier tipo de objeto como contenido. Por ejemplo, el siguiente código crea un elemento que contiene un número de punto flotante como contenido:

XElement n = new XElement("Cost", 324.50);
Console.WriteLine(n);

Este ejemplo produce el siguiente resultado:

<Cost>324.5</Cost>

Al número de punto flotante se le aplica la conversión boxing y se pasa al constructor. El número se convierte entonces en una cadena y se utiliza como contenido del elemento.

Ejemplo: Creación de XElement con un elemento secundario

Si pasa una instancia de la clase XElement para el argumento del contenido, el constructor creará un elemento que tiene un elemento secundario:

XElement shippingUnit = new XElement("ShippingUnit",
    new XElement("Cost", 324.50)
);
Console.WriteLine(shippingUnit);

Este ejemplo produce el siguiente resultado:

<ShippingUnit>
  <Cost>324.5</Cost>
</ShippingUnit>

Ejemplo: Creación de XElement con varios elementos secundarios

Para el contenido, puede pasar tantos objetos XElement como desee. Cada uno de los objetos XElement se incluye como elemento secundario.

XElement address = new XElement("Address",
    new XElement("Street1", "123 Main St"),
    new XElement("City", "Mercer Island"),
    new XElement("State", "WA"),
    new XElement("Postal", "68042")
);
Console.WriteLine(address);

Este ejemplo produce el siguiente resultado:

<Address>
  <Street1>123 Main St</Street1>
  <City>Mercer Island</City>
  <State>WA</State>
  <Postal>68042</Postal>
</Address>

Si amplía el ejemplo anterior, puede crear un árbol XML completo, como se indica:

XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"),
            new XElement("Phone", "206-555-0144"),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );
Console.WriteLine(contacts);

Este ejemplo produce el siguiente resultado:

<Contacts>
  <Contact>
    <Name>Patrick Hines</Name>
    <Phone>206-555-0144</Phone>
    <Address>
      <Street1>123 Main St</Street1>
      <City>Mercer Island</City>
      <State>WA</State>
      <Postal>68042</Postal>
    </Address>
  </Contact>
</Contacts>

Ejemplo: Creación de XElement con XAttribute

Si pasa una instancia de la clase XAttribute para el argumento del contenido, el constructor creará un elemento con un atributo:

XElement phone = new XElement("Phone",
    new XAttribute("Type", "Home"),
    "555-555-5555");
Console.WriteLine(phone);

Este ejemplo produce el siguiente resultado:

<Phone Type="Home">555-555-5555</Phone>

Ejemplo: Creación de un elemento vacío

Para crear un elemento XElement vacío, no pase ningún contenido al constructor. El siguiente ejemplo crea un elemento vacío:

XElement n = new XElement("Customer");
Console.WriteLine(n);

Este ejemplo produce el siguiente resultado:

<Customer />

Ejemplo: Asociación frente a clonación

Como mencionamos anteriormente, cuando se agregan objetos XNode (incluyendo el objeto XElement) o XAttribute, si el contenido nuevo no tiene un elemento primario, los objetos simplemente se adjuntan al árbol XML. Si el contenido nuevo ya tiene un elemento primario y forma parte de otro árbol XML, el nuevo contenido se clonará y ese clon se asociará al árbol XML.

En el siguiente ejemplo se muestra lo que ocurre si se agrega un elemento con elemento primario a un árbol, y lo que ocurre si se agrega un elemento sin elemento primario a un árbol:

// Create a tree with a child element.
XElement xmlTree1 = new XElement("Root",
    new XElement("Child1", 1)
);

// Create an element that's not parented.
XElement child2 = new XElement("Child2", 2);

// Create a tree and add Child1 and Child2 to it.
XElement xmlTree2 = new XElement("Root",
    xmlTree1.Element("Child1"),
    child2
);

// Compare Child1 identity.
Console.WriteLine("Child1 was {0}",
    xmlTree1.Element("Child1") == xmlTree2.Element("Child1") ?
    "attached" : "cloned");

// Compare Child2 identity.
Console.WriteLine("Child2 was {0}",
    child2 == xmlTree2.Element("Child2") ?
    "attached" : "cloned");

// This example produces the following output:
//    Child1 was cloned
//    Child2 was attached

Consulte también