Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
Guida al Visual Basic .NET - Manipolazione di file XML

Guida al Visual Basic .NET

Capitolo 99° - Manipolazione di file XML

<< Precedente Prossimo >>

XML è un acronimo per eXtensibale Markup Language (Linguaggio di Contrassegno Estensibile). Si tratta di un linguaggio per mezzo del quale è possibile immagazzinare dati in una struttura fortemente gerarchica e organizzata, un modello ideale che rispecchia appieno il meccanismo della programmazione orientata agli oggetti. L'XML è oggi usatissimo in un gran numero di casi, e la sua grande diffusione si deve attribuire alla sua flessibilità. Non so se "i miei venticinque lettori" conoscano l'HTML, ma è probabile di sì. Nell'HTML ci sono tag e proprietà definiti: il web master può usare solamente quelli. Al contrario, in XML è il programmatore che definisce i tag e gli attributi, ossia la grammatica con cui il documento viene scritto.
Prima di iniziare, segue una breve introduzione all'XML.

Introduzione all'XML

Un documento XML è un file di testo contenente dati incasellati in una struttura gerarchico-logica fortemente definita. Ogni parte di questa struttura viene detta elemento (o nodo in analogia con la formazione "ad albero" già descritta con il controllo TreeView). Ogni elemento può possedere informazioni ulteriori che ne specificano le proprietà peculiari: tali informazioni sono specificate sotto forma di attributi. L'elemento principale, di ordine superiore a tutti gli altri, si chiama elemento root o semplicemente root. L'unica entità in grado di stare allo stesso livello del root è la dichiarazione della versione xml o altre direttive di interpretazione. Ecco un esempio di semplice file:

<?xml version="1.0" ?>
<biblioteca>
<libro titolo="I sei numeri dell'universo" autore="Martin Rees">
    <capitolo titolo="Il cosmo e il microcosmo" numero="1" pagina="11">
        Alla base della struttura del nostro universo - non solo ...
    </capitolo>
</libro>
<libro titolo="Le ostinazioni di un matematico" autore="Didier Nordon">
    <capitolo titolo="Dalle stalle alle stelle" numero="1" pagina="11">
        Ecco a voi un romanzo il cui protagonista conosce una morte ...
    </capitolo>
</libro>
</biblioteca> 

Questo codice sintetizza i primi due libri che mi sono capitati in mano: ne specifica alcuni dettagli e riporta un pezzo della prima frase del primo capitolo. Partendo da questo sorgente, biblioteca, libro e capitolo sono elementi, mentre titolo, autore, numero e pagina sono attributi di questi elementi. Biblioteca è il root. Dopo aver letto e individuato le varie parti del documento, bisogna fare alcune osservazioni:

  • Tutti i valori, qualsiasi sia il loro tipo, vanno racchiusi tra apici singoli o doppi
  • Ogni elemento aperto deve essere chiuso. Se un elemento non ha contenuto si può usare la sintassi abbreviata
    <elemento attributo="valore" ... /> 
  • Tutto il testo è analizzato dai parser in modalità case-sensitive
  • Ogni identificatore di elemento o attributo deve essere un nome valido. Per questo verso segue le stesse regole per la creazione di un nome di variabile VB, ad eccezione della possibilità di usare il trattino

Il fatto che ci sia piena libertà nella creazione dei nomi e della propria grammatica non deve far considerare l'XML come un linguaggio poco rigoroso. Ci sono, infatti, degli speciali tipi di file, detti Schema, che sono in grado di definire con correttezza e precisione tutta la grammatica di un dato tipo di documenti: possono indicare, ad esempio, quali tag possono essere nidificati in quali altri; quali valori possa assumere un dato attributo; quanti elementi sia possibile definire per un certo tag padre; eccetera... Queste regole sono talmente potenti che esistono dei parser, ossia interpretatori di codice, che possono fornire gli stessi suggerimenti che fornisce l'Intellisense del .Net per un dato Schema, oltre al fatto di poter convalidare un documento controllando che vengano rispettati i principi definiti. Dato che questo non è un corso di XML, con l'introduzione mi fermo qui, ma siete liberi di approfondire l'argomento in altra sede, ad esempio qui.

Uso di XML in ambiente .NET

Descrivere dettagliatamente tutte le classi atte alla manipolazione dei documenti XML sarebbe un enorme spreco di tempo, e sicuramente non aiuterebbe poi molto: inoltre una documentazione esauriente e dettagliata esiste già all'interno della libreria MSDN di Microsoft. In questo paragrafo elencherò brevemente tali classi con una piccola descrizione:

  • System.Xml.XmlAttribute : rappresenta un attributo
  • System.Xml.XmlCDataSection : rappresenta una sezione CData. Questo tipo di elemento è un contenitore di testo esteso, al cui interno si possono dichiarare anche pezzi di codice XML: in questo modo essi non si confondono con il resto del documento
  • System.Xml.XmlComment : rappresenta un commento
  • System.Xml.XmlDocument : rappresenta un intero documento XML ed espone metodi per il salvataggio e il caricamento veloce
  • System.Xml.XmlElement : rappresenta un singolo elemento
  • System.Xml.XmlNode : rapprsenta un nodo. Da questa classe derivano molte altre
  • System.Xml.XmlReader : classe astratta di base per XmlTextReader e XmlValidatigReader, che consentono rispettivamente la lettura di testo xml o di uno schema xml
  • System.Xml.XmlWriter : classe astratta di base per XmlTextWriter, che consente la scrittura di testo xml sul documento

Di quelli elencati, che già sono una ristretta minoranza rispetto a quelli effettivamente presenti, noi useremo solo XmlTextReader e XmlTextWriter.

Iniziamo con XmlTextRaeder. Questa classe espone una quantità gigantesca di membri, che sarebbe troppo dispendioso elencare completamente. Il suo funzionamento non è semplicissimo da capire a un primo impatto, ma un poco di ragionamento lo renderà più chiaro. La funzione principale è Read, che legge un nodo e restituisce False se non c'è niente da leggere. Una volta letto, le sue informazioni diventano disponibili attraverso le proprietà di XmlTextReader, che funge da totum continens: infatti gli attributi e i contenuti vengono letti tutti nello stesso modo, considerati, quindi, tutti nodi. Ecco un esempio che prende un file XML, lo analizza e lo restituisce sotto forma di file INI (anche se questo non supporta la gerarchia):

Imports System.Xml
Module Module1
    Sub Main()
        'Crea un nuovo lettore xml.
        Dim Reader As New Xml.XmlTextReader("C:libri.xml")
        Dim Indent, Content As String

        'La funzione Reader.Read legge il nodo successivo e
        'restituisce False se non c'è niente altro da
        'leggere. Il ciclo legge tutti gli elementi
        Do While Reader.Read
            'Indenta il codice a seconda della profondità
            'del nodo
            Indent = New String(" ", Reader.Depth * 2)
            'Se il nodo è un tag di chiusura, come ad
            'esempio </libro>, lo salta
            If Not Reader.IsStartElement Then
                'Viene considerato un nodo anche il testo all'interno
                'di un elemento, perciò bisogna controllare
                'se questo non sia effettivamente un testo
                If Reader.HasValue Then
                    Console.WriteLine(Reader.Value)
                End If
                Continue Do
            End If

            'Scrive il nome del tag a schermo, tra parentesi quadre,
            'come nei file INI
            Console.WriteLine("{0}[{1}]", Indent, Reader.Name)
            'Se l'elemento ha un contenuto, lo memorizza per scriverlo
            'successivamente a schermo
            If Reader.HasValue AndAlso Reader.Value <> vbCrLf Then
                Content = Reader.Value
            Else
                Content = Nothing
            End If
            'Se l'elemento possiede attributi, li scrive
            If Reader.HasAttributes Then
                For I As Int16 = 0 To Reader.AttributeCount - 1
                    Reader.MoveToAttribute(I)
                    Console.WriteLine("{0}{1} = {2}", Indent, _ 
                        Reader.Name, Reader.Value)
                Next
            End If

            If Content IsNot Nothing Then
                Console.WriteLine("{0}Contenuto = {1}", Indent, Content)
            End If
        Loop
        Reader.Close()

        Console.ReadKey()
    End Sub
End Module 

Il risultato sarà questo:

[biblioteca]
  [libro]
  titolo = I sei numeri dell'universo
  autore = Martin Rees
    [capitolo]
    titolo = Il cosmo e il microcosmo
    numero = 1
    pagina = 11
        
        Alla base della struttura del nostro universo - non solo ...
        
  [libro]
  titolo = Le ostinazioni di un matematico
  autore = Didier Nordon
    [capitolo]
    titolo = Dalle stalle alle stelle
    numero = 1
    pagina = 11
    
        Ecco a voi un romanzo il cui protagonista conosce una morte ... 


Passiamo ora a XmlTextWriter: i suoi membri sono molto meno numerosi ed usarlo è assai semplice. Quasi tutti i metodi iniziano per "Write" e servono a scrivere diversi tipi di dati, elementi, attributi e specifiche del documento. La cosa importante da ricordarsi quando si lavora con XmlTextWriter è di richiamare sempre, prima di ogni metodo, WriteStartDocument, che si occupa di inizializzare il documento correttamente con le direttive adatte; e dopo aver terminato le varie operazioni WriteEndDocument, che chiude tutto. Ecco un esempio:

Imports System.Text
Imports System.Xml
Module Module2
    Sub Main()
        'Il secondo parametro del costruttore è obbligatorio
        'e specifica quale codifica di caratteri si debba usare.
        'In questo caso ho messo UTF-8, in modo da poter usare anche
        'i caratteri accentati
        Dim Writer As New XmlTextWriter("C:guida.xml", UTF8Encoding.UTF8)

        With Writer
            .Indentation = 2
            .IndentChar = " "

            'Scrive l'intestazione
            .WriteStartDocument()

            'Scrive l'elemento root
            .WriteStartElement("guida")
            'E l'attributo "capitoli"
            .WriteAttributeString("capitoli", "100")

            'Scrive un elemento capitolo
            .WriteStartElement("capitolo")
            .WriteAttributeString("numero", "1")
            .WriteAttributeString("titolo", "Introduzione")
            .WriteString("A differenza del Visual Basic classico, ...")
            .WriteEndElement()

            'Chiude il root e il documento
            .WriteEndElement()
            .WriteEndDocument()
            .Close()
        End With
        Console.ReadKey()
    End Sub
End Module 
<< Precedente Prossimo >>
A proposito dell'autore

Programmatore e analista .NET 2005/2008/2010 (in particolare C# e VB.NET), anche nell'implementazione Mono per Linux. Conoscenze approfondite di Pascal, PHP, XML, HTML 4.01/5, CSS 2.1/3, Javascript (e jQuery). Conoscenze buone di C, LUA, GML, Ruby, XNA, AJAX e Assembly 68000. Competenze basilari di C++, SQL, Hlsl, Java.