Creare alberi XML in C# (LINQ to XML)

Questo articolo fornisce informazioni sulla creazione di alberi XML in C#.

Per informazioni sull'uso dei risultati delle query LINQ come contenuto per un oggetto XElement, vedere Costruzione funzionale.

Costruire elementi

Le firme dei costruttori XElement e XAttribute consentono di passare come argomenti del costruttore il contenuto dell'elemento o dell'attributo. Poiché uno dei costruttori accetta un numero variabile di argomenti, è possibile passare un qualsiasi numero di elementi figlio. Ognuno degli elementi figlio può naturalmente contenere elementi figlio. Per qualsiasi elemento è possibile aggiungere un qualsiasi numero di attributi.

Se quando si aggiungono oggetti XNode (incluso XElement) o XAttribute, il nuovo contenuto non ha elementi padre, gli oggetti vengono semplicemente collegati all'albero XML. Se invece il nuovo contenuto include già elementi padre e fa parte di un altro albero XML, viene duplicato e quindi collegato all'albero XML. Questo comportamento è illustrato nell'ultimo esempio di questo articolo.

Per creare un oggetto contactsXElement, è possibile usare il codice seguente:

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")
            )
        )
    );

Se i rientri sono stati impostati correttamente, il codice per costruire oggetti XElement è molto simile alla struttura del codice XML sottostante.

Costruttori XElement

La classe XElement usa i costruttori seguenti per la costruzione funzionale. Notare che esistono altri costruttori per XElement, che tuttavia non vengono elencati in questa sede perché non usati per la costruzione funzionale.

Costruttore Descrizione
XElement(XName name, object content) Crea un oggetto XElement. Il parametro name specifica il nome dell'elemento, mentre il parametro content ne specifica il contenuto.
XElement(XName name) Crea un oggetto XElement il cui XName viene inizializzato in base al nome specificato.
XElement(XName name, params object[] content) Crea un oggetto XElement il cui XName viene inizializzato in base al nome specificato. Gli attributi e/o elementi figlio vengono creati dal contenuto dell'elenco di parametri.

Il parametro content è estremamente flessibile. Supporta qualsiasi tipo di oggetto che sia un elemento figlio valido di un oggetto XElement. Ai tipi diversi di oggetti passati in questo parametro si applicano le regole seguenti:

  • Una stringa viene aggiunta come contenuto di tipo testo.
  • Un oggetto XElement viene aggiunto come elemento figlio.
  • Un oggetto XAttribute viene aggiunto come attributo.
  • Un oggetto XProcessingInstruction, XComment o XText viene aggiunto come contenuto di elemento figlio.
  • Viene enumerato un oggetto IEnumerable e queste regole vengono applicate in modo ricorsivo ai risultati.
  • Per qualsiasi altro tipo viene chiamato il metodo ToString e il risultato viene aggiunto come contenuto di tipo testo.

Esempio: creare un XElement con contenuto

È possibile creare un oggetto XElement con contenuto semplice usando una sola chiamata di metodo. A tale scopo, specificare il contenuto come secondo parametro, come illustrato di seguito:

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

Nell'esempio viene prodotto l'output seguente:

<Customer>Adventure Works</Customer>

È possibile passare come contenuto qualsiasi tipo di oggetto. Ad esempio, nel codice seguente viene creato un elemento il cui contenuto è un numero a virgola mobile:

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

Nell'esempio viene prodotto l'output seguente:

<Cost>324.5</Cost>

Il numero a virgola mobile viene sottoposto a boxing e quindi passato al costruttore. Il numero boxed viene convertito in una stringa e usato come contenuto dell'elemento.

Esempio: creare un XElement con un elemento figlio

Se si passa un'istanza della classe XElement come argomento del contenuto, il costruttore crea un elemento con un elemento figlio:

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

Nell'esempio viene prodotto l'output seguente:

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

Esempio: creare un XElement con più elementi figlio

È possibile passare più oggetti XElement per il contenuto. Ognuno degli oggetti XElement viene incluso come elemento figlio.

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);

Nell'esempio viene prodotto l'output seguente:

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

Estendendo l'esempio precedente è possibile creare un intero albero XML, come illustrato di seguito:

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);

Nell'esempio viene prodotto l'output seguente:

<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>

Esempio: creare un XElement con XAttribute

Se si passa un'istanza della classe XAttribute come argomento del contenuto, il costruttore crea un elemento con un attributo:

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

Nell'esempio viene prodotto l'output seguente:

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

Esempio: creare un elemento vuoto

Per creare un oggetto XElement vuoto, non passare contenuto al costruttore. Nell'esempio seguente creato un elemento vuoto.

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

Nell'esempio viene prodotto l'output seguente:

<Customer />

Esempio: differenza tra collegare e clonare

Come accennato in precedenza, se quando si aggiungono oggetti XNode (incluso XElement) o XAttribute, il nuovo contenuto non ha elementi padre, gli oggetti vengono semplicemente collegati all'albero XML. Se invece il nuovo contenuto include già elementi padre e fa parte di un altro albero XML, viene duplicato e quindi collegato all'albero XML.

L'esempio seguente illustra il diverso comportamento quando si aggiunge un elemento con o senza elemento padre a una struttura ad albero:

// 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

Vedi anche