Compartir a través de


LINQ to XML frente a DOM

En este artículo se describen algunas diferencias clave entre LINQ to XML y la API de programación XML predominante actual, el modelo de objetos de documento (DOM) W3C.

Nuevas formas de construir árboles XML

En el DOM de W3C, se crea un árbol XML desde abajo hacia arriba; es decir, se crea un documento, se crean elementos y, a continuación, se agregan los elementos al documento.

Por ejemplo, en el ejemplo siguiente se usa una manera típica de crear un árbol XML mediante la implementación de Microsoft de DOM, XmlDocument.

XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
XmlElement phone1 = doc.CreateElement("Phone");
phone1.SetAttribute("Type", "Home");
phone1.InnerText = "206-555-0144";
XmlElement phone2 = doc.CreateElement("Phone");
phone2.SetAttribute("Type", "Work");
phone2.InnerText = "425-555-0145";
XmlElement street1 = doc.CreateElement("Street1");
street1.InnerText = "123 Main St";
XmlElement city = doc.CreateElement("City");
city.InnerText = "Mercer Island";
XmlElement state = doc.CreateElement("State");
state.InnerText = "WA";
XmlElement postal = doc.CreateElement("Postal");
postal.InnerText = "68042";
XmlElement address = doc.CreateElement("Address");
address.AppendChild(street1);
address.AppendChild(city);
address.AppendChild(state);
address.AppendChild(postal);
XmlElement contact = doc.CreateElement("Contact");
contact.AppendChild(name);
contact.AppendChild(phone1);
contact.AppendChild(phone2);
contact.AppendChild(address);
XmlElement contacts = doc.CreateElement("Contacts");
contacts.AppendChild(contact);
doc.AppendChild(contacts);
Dim doc As XmlDocument = New XmlDocument()
Dim name As XmlElement = doc.CreateElement("Name")
name.InnerText = "Patrick Hines"
Dim phone1 As XmlElement = doc.CreateElement("Phone")
phone1.SetAttribute("Type", "Home")
phone1.InnerText = "206-555-0144"
Dim phone2 As XmlElement = doc.CreateElement("Phone")
phone2.SetAttribute("Type", "Work")
phone2.InnerText = "425-555-0145"
Dim street1 As XmlElement = doc.CreateElement("Street1")
street1.InnerText = "123 Main St"
Dim city As XmlElement = doc.CreateElement("City")
city.InnerText = "Mercer Island"
Dim state As XmlElement = doc.CreateElement("State")
state.InnerText = "WA"
Dim postal As XmlElement = doc.CreateElement("Postal")
postal.InnerText = "68042"
Dim address As XmlElement = doc.CreateElement("Address")
address.AppendChild(street1)
address.AppendChild(city)
address.AppendChild(state)
address.AppendChild(postal)
Dim contact As XmlElement = doc.CreateElement("Contact")
contact.AppendChild(name)
contact.AppendChild(phone1)
contact.AppendChild(phone2)
contact.AppendChild(address)
Dim contacts As XmlElement = doc.CreateElement("Contacts")
contacts.AppendChild(contact)
doc.AppendChild(contacts)
Console.WriteLine(doc.OuterXml)

Este estilo de codificación oculta la estructura del árbol XML. LINQ to XML también admite un enfoque alternativo, construcción funcional, que muestra mejor la estructura. Este enfoque se puede realizar con los constructores XElement y XAttribute. En Visual Basic, también se puede hacer con literales XML. En este ejemplo se muestra la construcción del mismo árbol XML mediante la construcción funcional:

XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"),
            new XElement("Phone", "206-555-0144",
                new XAttribute("Type", "Home")),
            new XElement("phone", "425-555-0145",
                new XAttribute("Type", "Work")),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );
Dim contacts = _
    <Contacts>
        <Contact>
            <Name>Patrick Hines</Name>
            <Phone Type="Home">206-555-0144</Phone>
            <Phone Type="Work">425-555-0145</Phone>
            <Address>
                <Street1>123 Main St</Street1>
                <City>Mercer Island</City>
                <State>WA</State>
                <Postal>68042</Postal>
            </Address>
        </Contact>
    </Contacts>

Observa que al indentar el código para construir el árbol XML se muestra la estructura del XML subyacente. La versión de Visual Basic usa literales XML.

Para obtener más información, vea Árboles XML.

Trabajar directamente con elementos XML

Al programar con XML, el enfoque principal suele estar en elementos XML y quizás en atributos. En LINQ to XML, puede trabajar directamente con atributos y elementos XML. Por ejemplo, puede hacer lo siguiente:

  • Cree elementos XML sin usar ningún objeto de documento. Esto simplifica la programación cuando tiene que trabajar con fragmentos de árboles XML.
  • Cargue T:System.Xml.Linq.XElement objetos directamente desde un archivo XML.
  • Serialice T:System.Xml.Linq.XElement objetos en un archivo o un flujo.

Compare esto con el DOM de W3C, en el que el documento XML se usa como contenedor lógico para el árbol XML. En DOM, los nodos XML, incluidos los elementos y atributos, deben crearse en el contexto de un documento XML. Este es un fragmento de código para crear un elemento name en DOM:

XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
doc.AppendChild(name);
Dim doc As XmlDocument = New XmlDocument()
Dim name As XmlElement = doc.CreateElement("Name")
name.InnerText = "Patrick Hines"
doc.AppendChild(name)

Si desea usar un elemento en varios documentos, debe importar los nodos entre documentos. LINQ to XML evita esta capa de complejidad.

Al usar LINQ to XML, use la XDocument clase solo si desea agregar un comentario o una instrucción de procesamiento en el nivel raíz del documento.

Control simplificado de nombres y espacios de nombres

Controlar nombres, espacios de nombres y prefijos de espacios de nombres suele ser una parte compleja de la programación XML. LINQ to XML simplifica los nombres y los espacios de nombres al eliminar el requisito de tener que tratar con prefijos de espacios de nombres. Si desea controlar los prefijos de espacio de nombres, puede hacerlo. Pero si decide no controlar explícitamente los prefijos de espacios de nombres, durante la serialización, LINQ to XML asignará prefijos de espacios de nombres si son necesarios, o serializará con espacios de nombres predeterminados si no lo son. Si se usan espacios de nombres predeterminados, no habrá prefijos de espacio de nombres en el documento resultante. Para obtener más información, consulte Descripción general de los espacios de nombres.

Otro problema con dom es que no permite cambiar el nombre de un nodo. En su lugar, debe crear un nuevo nodo y copiar todos los nodos secundarios en él, lo que pierde la identidad del nodo original. LINQ to XML evita este problema al permitirle establecer la XName propiedad en un nodo.

Compatibilidad con métodos estáticos para cargar XML

LINQ to XML permite cargar XML mediante métodos estáticos, en lugar de métodos de instancia. Esto simplifica la carga y el análisis. Para obtener más información, vea Cómo cargar XML desde un archivo.

Eliminación de la compatibilidad con construcciones DTD

LINQ to XML simplifica aún más la programación XML quitando la compatibilidad con entidades y referencias de entidad. La administración de entidades es compleja y rara vez se usa. La eliminación de su compatibilidad aumenta el rendimiento y simplifica la interfaz de programación. Cuando se rellena un árbol LINQ to XML, se expanden todas las entidades DTD.

Compatibilidad con fragmentos

LINQ to XML no proporciona un equivalente para la XmlDocumentFragment clase . En cambio, es bastante común que el concepto XmlDocumentFragment se pueda controlar mediante el resultado de una consulta que se escribe como IEnumerable<T> de XNode o IEnumerable<T> de XElement.

Compatibilidad con XPathNavigator

LINQ to XML proporciona compatibilidad con XPathNavigator mediante los métodos de extensión del espacio de nombres System.Xml.XPath. Para obtener más información, consulte System.Xml.XPath.Extensions.

Compatibilidad con espacios en blanco y sangría

LINQ to XML controla el espacio en blanco más simplemente que el DOM.

Un caso muy común es aquel en el que se leen datos XML con sangría, se crea un árbol XML en memoria sin ningún nodo de texto con espacios en blanco (es decir, sin conservar los espacios en blanco), se realizan ciertas operaciones sobre el XML y este se guarda con sangría. Al serializar el XML con formato, solo se conserva un espacio en blanco significativo en el árbol XML. Este es el comportamiento predeterminado para LINQ to XML.

Otro escenario común es leer y modificar XML que ya ha sido indentado intencionadamente. Es posible que no desee modificar esta sangría de ninguna forma. En LINQ to XML, puede hacerlo mediante:

  • Conservar el espacio en blanco al cargar o analizar el XML.
  • Deshabilitación del formato al serializar el XML.

LINQ to XML almacena espacios en blanco como un XText nodo, en lugar de tener un tipo de nodo especializado Whitespace , como hace el DOM.

Compatibilidad con anotaciones

Los elementos LINQ to XML admiten un conjunto extensible de anotaciones. Esto resulta útil para realizar un seguimiento de información varias sobre un elemento, como información de esquema, información sobre si el elemento está enlazado a una interfaz de usuario o a cualquier otro tipo de información específica de la aplicación. Para más información, consulte Anotaciones en LINQ to XML.

Compatibilidad con la información de esquema

LINQ to XML proporciona compatibilidad con la validación XSD mediante métodos de extensión en el espacio de nombres System.Xml.Schema. Puede validar que un árbol XML cumple con un XSD. Puede rellenar el árbol XML con el conjunto de información posterior a la validación del esquema (PSVI). Para obtener más información, vea Cómo validar el uso de XSD y Extensions.

Consulte también