LINQ to XML vs. DOM
Esta sección describe algunas diferencias fundamentales entre LINQ to XML y la API de programación XML predominante actual, el modelo de objetos de documento W3C.
Nuevas formas de crear árboles XML
En DOM W3C, los árboles XML se crean de abajo arriba; es decir, se crea un documento, se crean elementos y, a continuación, se agregan los elementos al documento.
Por ejemplo, a continuación se muestra una forma típica de crear un árbol XML usando la implementación de DOM de Microsoft, 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 no proporciona mucha información visual acerca de la estructura del árbol XML. LINQ to XML admite este enfoque para crear un árbol XML, pero también admite un enfoque alternativo, la construcción funcional. La construcción funcional usa los constructores XElement y XAttribute para crear un árbol XML.
A continuación se muestra cómo se crea el mismo árbol XML usando la construcción funcional LINQ to XML:
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")
)
)
);
Tenga en cuenta que si se aplica la sangría al código para crear el árbol XML, se mostrará la estructura XML subyacente.
En Visual Basic, el código para crear el árbol XML es incluso más sencillo, ya que usa un literal XML:
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>
Si tiene un documento XML y desea crear un árbol XML a partir de él, puede abrir el documento XML en un editor, copiar el código XML en el portapapeles, abrir un módulo de Visual Basic en Visual Studio y pegar el código XML directamente en el editor de código de Visual Basic.
Para obtener más información, consulta Crear árboles XML.
Trabajar directamente con elementos XML
La programación con XML suele centrarse en elementos XML y quizás en los atributos. En LINQ to XML, se puede trabajar directamente con atributos y elementos XML. Por ejemplo, puede realizar lo siguiente:
Crear elementos XML sin usar un objeto de documento. Esto simplifica la programación cuando se tiene que trabajar con fragmentos de árboles XML.
Cargar objetos T:System.Xml.Linq.XElement directamente de un archivo XML.
Serializar objetos T:System.Xml.Linq.XElement a un archivo o una secuencia.
Compare esto con modelo DOM del consorcio W3C, en el que el documento XML se usa como contenedor lógico para el árbol XML. En DOM, los nodos XML, incluyendo elementos y atributos, se deben crear en el contexto de un documento XML. A continuación se muestra un fragmento del código para crear un nombre de elemento 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 en los documentos. LINQ to XML evita este grado de complejidad.
Cuando se utiliza LINQ to XML, se usa la clase XDocument solamente si se desea agregar un comentario o una instrucción de procesamiento en el nivel de 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 eliminando el requisito de tratar los prefijos de espacios de nombres. Si lo desea, puede controlar los prefijos de espacios de nombres. 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á usando espacios de nombres predeterminados si no lo son. Si se usan espacios de nombres predeterminados, no habrá prefijos de espacios de nombres en el documento resultante. Para obtener más información, vea Trabajar con espacios de nombres XML.
Otro problema de DOM consiste en que no permite cambiar el nombre de un nodo. Por el contrario, hay que crear un nuevo nodo y copiar en él todos los nodos secundarios, por lo que se pierde la identidad del nodo original. LINQ to XML evita este problema al permitir que se establezca la propiedad XName en un nodo.
Compatibilidad con el método estático para cargar XML
LINQ to XML permite cargar XML usando 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, consulta Cómo cargar XML de 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 a entidades. La administración de entidades es compleja y su uso es muy poco común. La eliminación de la compatibilidad aumenta el rendimiento y simplifica la interfaz de programación. Cuando se rellena un árbol de LINQ to XML, se expanden todas las entidades DTD.
Compatibilidad con fragmentos
LINQ to XML no proporciona un equivalente para la clase XmlDocumentFragment. No obstante, es bastante común que el concepto XmlDocumentFragment se pueda controlar mediante el resultado de una consulta que se escribe como IEnumerable de XNode o IEnumerable 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, consulta Extensions.
Compatibilidad con espacios en blanco y sangría
LINQ to XML trata los espacios en blanco de forma más sencilla que 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 preservar los espacios en blanco), se realizan ciertas operaciones sobre el XML y éste se guarda con sangría. Si se serializa el XML con formato, solo se preservan en el XML aquellos espacios en blanco más significativos. Éste es el comportamiento predeterminado en LINQ to XML.
Otro escenario muy común es aquel en el que se lee y se modifica código XML en el que se ha aplicado sangría de forma intencionada. Es posible que no desee modificar esta sangría de ninguna forma. En LINQ to XML, puede conseguirlo si preserva los espacios en blanco a la hora de cargar o analizar el XML y si deshabilita el formato cuando serialice el XML.
LINQ to XML almacena un espacio en blanco como un nodo XText, en lugar de tener un tipo de nodo Whitespace especializado, al igual que DOM.
Compatibilidad con anotaciones
Los elementos de LINQ to XML admiten un conjunto extensible de anotaciones. Esto puede resultar útil para realizar un seguimiento de información diversa de un elemento, como la información de esquema, información acerca de si un elemento está enlazado a una interfaz de usuario o cualquier otro tipo de información específica de una aplicación. Para obtener más información, consulta 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 sea compatible 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 con XSD (LINQ to XML) y Extensions.