LINQ to XML e DOM

Questo articolo descrive alcune delle principali differenze tra LINQ to XML e l'API di programmazione XML attualmente più diffusa, ovvero DOM (Document Object Model) W3C.

Nuove modalità di creazione degli alberi XML

In W3C DOM un albero XML viene compilata dal basso verso l'alto, ossia si crea un documento, si creano gli elementi e quindi si aggiungono gli elementi al documento.

Nell'esempio seguente viene illustrata una modalità standard di creazione di un albero XML tramite l'implementazione Microsoft di DOM, ovvero 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)

Questo stile di scrittura del codice nasconde la struttura dell'albero XML. LINQ to XML supporta anche un approccio alternativo, la costruzione funzionale, che illustra meglio la struttura. Per mettere in pratica questo approccio, si usano i costruttori XElement e XAttribute. In Visual Basic è anche possibile usare valori letterali XML. In questo esempio viene illustrata la costruzione dello stesso albero XML con la costruzione funzionale:

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>

Si noti che il rientro del codice per costruire la struttura ad albero XML illustra la struttura dell'XML sottostante. Nella versione per Visual Basic vengono usati valori letterali XML.

Per altre informazioni, vedere Alberi XML.

Usare direttamente gli elementi XML

Quando si programma con XML, l'obiettivo principale riguarda in genere gli elementi XML e talvolta gli attributi. In LINQ to XML è possibile usare direttamente gli elementi e gli attributi XML. È ad esempio possibile eseguire le seguenti operazioni:

  • Creare elementi XML senza usare affatto un oggetto documento. In questo modo la programmazione risulta semplificata quando è necessario usare frammenti di alberi XML.
  • Caricare oggetti T:System.Xml.Linq.XElement direttamente da un file XML.
  • Serializzare oggetti T:System.Xml.Linq.XElement a un file o un flusso.

Al contrario, in W3C DOM il documento XML viene usato come contenitore logico per l'albero XML. In DOM i nodi XML, inclusi elementi e attributi, devono essere creati nel contesto di un documento XML. Ecco un frammento del codice usato per creare un elemento name in 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)

Se si desidera usare un elemento in più documenti, è necessario importare i nodi tra documenti. In LINQ to XML questo livello di complessità viene evitato.

Con LINQ to XML la classe XDocument viene usata solo se si desidera aggiungere un commento o un'istruzione di elaborazione al livello radice del documento.

Gestione semplificata di nomi e spazi dei nomi

La gestione di nomi, spazi dei nomi e prefissi di spazio dei nomi è in genere un aspetto complesso della programmazione XML. In LINQ to XML nomi e spazi dei nomi sono semplificati perché non è necessario gestire i prefissi di spazio dei nomi. Se si desidera, è possibile controllare i prefissi di spazio dei nomi. Se tuttavia si decide di non controllare in modo esplicito i prefissi, durante la serializzazione LINQ to XML assegnerà i prefissi di spazio dei nomi, se sono necessari, oppure eseguirà la serializzazione usando spazi dei nomi predefiniti, se non sono necessari. Se vengono utilizzati gli spazi dei nomi predefiniti, il documento risultante non conterrà prefissi di spazio dei nomi. Per altre informazioni, vedere Panoramica degli spazi dei nomi.

Un altro problema di DOM è che non consente di modificare il nome di un nodo. È invece necessario creare un nuovo nodo e copiarvi tutti i nodi figlio, perdendo l'identità del nodo originale. In LINQ to XML è possibile evitare questo problema perché consente di impostare la proprietà XName su un nodo.

Supporto dei metodi statici per il caricamento di codice XML

LINQ to XML consente di caricare XML usando metodi statici, invece di metodi di istanza. semplificando le operazioni di caricamento e analisi. Per altre informazioni, vedere Come caricare XML da un file.

Rimozione del supporto per i costrutti DTD

Con LINQ to XML la programmazione XML risulta ancora più agevole, perché viene eliminato il supporto per le entità e i riferimenti alle entità. Oltre a essere complessa, la gestione di entità viene utilizzata raramente. Rimuovendone il supporto è possibile riscontrare un aumento delle prestazioni e un'interfaccia di programmazione semplificata. Quando viene popolato un albero LINQ to XML, tutte le entità DTD vengono espanse.

Supporto per i frammenti

LINQ to XML non fornisce un equivalente per la classe XmlDocumentFragment. In molti casi, tuttavia, il concetto di XmlDocumentFragment può essere gestito dal risultato di una query digitato come IEnumerable<T> di XNode o IEnumerable<T> di XElement.

Supporto per XPathNavigator

LINQ to XML fornisce il supporto per XPathNavigator tramite metodi di estensione nello spazio dei nomi System.Xml.XPath. Per ulteriori informazioni, vedere System.Xml.XPath.Extensions.

Supporto per spazi e rientri

LINQ to XML gestisce più semplicemente gli spazi rispetto a DOM.

Uno scenario comune prevede che il codice XML venga letto con rientri, venga creato un albero XML in memoria senza nodi di testo con spazi (ossia senza conservare gli spazi), vengano eseguite alcune operazioni sul codice XML e il codice XML venga salvato senza rientri. Quando si serializza l'XML con la formattazione, nell'albero XML viene conservato solo lo spazio vuoto significativo. Questo è il comportamento predefinito per LINQ to XML.

In un altro scenario comune viene letto e modificato codice XML che è già stato intenzionalmente rientrato. È possibile che si desideri non modificare questo rientro in alcun modo. In LINQ to XML è possibile eseguire questa operazione nel modo seguente:

  • Mantenendo gli spazi quando si carica o si analizza il codice XML.
  • Disabilitando la formattazione quando si serializza il codice XML.

In LINQ to XML gli spazi vengono archiviati come nodo XText, invece di avere un tipo di nodo Whitespace specializzato, come invece avviene in DOM.

Supporto per le annotazioni

Gli elementi LINQ to XML supportano un set estendibile di annotazioni. Questa funzione è utile per tenere traccia di varie informazioni su un elemento, ad esempio informazioni sullo schema, informazioni su se l'elemento è associato a un'interfaccia utente o altri tipi di informazioni specifiche dell'applicazione. Per altre informazioni, vedere Annotazioni LINQ to XML.

Supporto per le informazioni sullo schema

LINQ to XML fornisce il supporto per la convalida XSD tramite metodi di estensione nello spazio dei nomi System.Xml.Schema. È possibile verificare che un albero XML sia conforme a un XSD. È possibile popolare l'albero XML con le informazioni sulla convalida post-schema. Per altre informazioni, vedere Come eseguire la convalida tramite XSD e Extensions.

Vedi anche