Lettura delle strutture XML

Flash Player 9 e versioni successive, Adobe AIR 1.0 e versioni successive

Una delle funzioni più sofisticate di XML è la sua abilità di creare strutture di dati complesse e nidificate mediante una stringa lineare di caratteri di testo. Durante il caricamento di dati di un oggetto XML, ActionScript analizza i dati e ne carica la struttura gerarchica in memoria (oppure genera un errore in fase di runtime se la sintassi dei dati XML contiene un errore).

Gli operatori e i metodi degli oggetti XML e XMLList rendono semplice la lettura della struttura dei dati XML.

Usate l'operatore punto (.) e l'operatore accessor discendente (..) per accedere alle proprietà secondarie di un oggetto XML. Osservate l'oggetto XML seguente:

var myXML:XML =  
    <order> 
        <book ISBN="0942407296"> 
            <title>Baking Extravagant Pastries with Kumquats</title> 
            <author> 
                <lastName>Contino</lastName> 
                <firstName>Chuck</firstName> 
            </author> 
            <pageCount>238</pageCount> 
        </book> 
        <book ISBN="0865436401"> 
            <title>Emu Care and Breeding</title> 
            <editor> 
                <lastName>Case</lastName> 
                <firstName>Justin</firstName> 
            </editor> 
            <pageCount>115</pageCount> 
        </book> 
    </order>

L'oggetto myXML.book è un oggetto XMLList che contiene proprietà secondarie dell'oggetto myXML denominato book. Sono due oggetti XML, che corrispondono alle due proprietà book dell'oggetto myXML.

L'oggetto myXML..lastName è un oggetto XMLList contenente qualsiasi proprietà discendente denominata lastName. Sono due oggetti XML, che corrispondono ai due lastName dell'oggetto myXML.

L'oggetto myXML.book.editor.lastName è un oggetto XMLList contenente qualsiasi proprietà discendente denominata lastName delle proprietà discendenti denominate editor delle proprietà discendenti denominate book dell'oggetto myXML: in questo caso, un oggetto XMLList contenente un solo oggetto XML (la proprietà lastName con il valore "Case").

Accesso ai nodi principali e secondari

Il metodo parent() restituisce il nodo principale di un oggetto XML.

Per accedere a oggetti secondari specifici, potete usare valori di indice ordinali di un elenco. Ad esempio, considerate un oggetto XML myXML che dispone di due proprietà secondarie denominate book. A ogni proprietà book secondaria è associato un numero di indice:

myXML.book[0] 
myXML.book[1]

Per accedere a un elemento secondario di secondo livello potete specificare il numero di indice sia dell'elemento secondario di primo livello che di quello di secondo livello:

myXML.book[0].title[0]

Tuttavia, se x.book[0] dispone di una sola proprietà secondaria denominata title, potete omettere il riferimento al numero di indice, come illustrato di seguito:

myXML.book[0].title

Analogamente, se esiste un solo oggetto secondario book dell'oggetto x, e se quell'oggetto secondario dispone di un solo oggetto title, potete omettere entrambi i riferimenti di indice, nel modo seguente:

myXML.book.title

Potete usare il metodo child() per andare agli elementi secondari con nomi basati su una variabile o un'espressione, come illustrato nell'esempio seguente:

var myXML:XML =  
        <order> 
            <book> 
                <title>Dictionary</title> 
            </book> 
        </order>; 
 
var childName:String = "book"; 
 
trace(myXML.child(childName).title) // output: Dictionary

Accesso agli attributi

Usate il simbolo @ (l'operatore identificatore di attributi) per accedere agli attributi di un oggetto XML o XMLList, come nel codice seguente:

var employee:XML =  
    <employee id="6401" code="233"> 
        <lastName>Wu</lastName> 
        <firstName>Erin</firstName> 
    </employee>; 
trace(employee.@id); // 6401

Per accedere a tutti gli attributi di un oggetto XML o XMLList potete usare il carattere jolly * combinato al simbolo @, come illustrato nel codice seguente:

var employee:XML =  
    <employee id="6401" code="233"> 
        <lastName>Wu</lastName> 
        <firstName>Erin</firstName> 
    </employee>; 
trace(employee.@*.toXMLString());  
// 6401 
// 233

Potete usare il metodo attribute() o il metodo attributes() per accedere a un attributo specifico o a tutti gli attributi di un oggetto XML o XMLList, come illustrato nel codice seguente:

var employee:XML =  
    <employee id="6401" code="233"> 
        <lastName>Wu</lastName> 
        <firstName>Erin</firstName> 
    </employee>; 
trace(employee.attribute("id")); // 6401 
trace(employee.attribute("*").toXMLString());  
// 6401 
// 233 
trace(employee.attributes().toXMLString());  
// 6401 
// 233

Notate che per accedere agli attributi potete anche utilizzare la sintassi seguente, come illustrato nell'esempio seguente:

employee.attribute("id") 
employee["@id"] 
employee.@["id"]

Tutte queste sono alternative equivalenti a employee.@id. Tuttavia, la sintassi employee.@id è l'approccio da preferirsi.

Filtraggio per attributo o elemento

Per filtrare gli elementi con un nome o valore di attributo specifico potete usare gli operatori parentesi: ( e ). Osservate l'oggetto XML seguente:

var x:XML =  
    <employeeList> 
        <employee id="347"> 
            <lastName>Zmed</lastName> 
            <firstName>Sue</firstName> 
            <position>Data analyst</position> 
        </employee> 
        <employee id="348"> 
            <lastName>McGee</lastName> 
            <firstName>Chuck</firstName> 
            <position>Jr. data analyst</position> 
        </employee> 
    </employeeList>

Tutte le espressioni seguenti sono valide:

  • x.employee.(lastName == "McGee") - Questo è il secondo nodo employee.

  • x.employee.(lastName == "McGee").firstName - Questa è la proprietà firstName del secondo nodo employee.

  • x.employee.(lastName == "McGee").@id - Questo è il valore dell'attributo id del secondo nodo employee.

  • x.employee.(@id == 347) - Il primo nodo employee.

  • x.employee.(@id == 347).lastName - Questa è la proprietà lastName del primo nodo employee.

  • x.employee.(@id > 300): questo è un oggetto XMLList con entrambe le proprietà employee.

  • x.employee.(position.toString().search("analyst") > -1): questo è un oggetto XMLList con entrambe le proprietà position.

Se tentate di applicare un filtro utilizzando attributi o elementi inesistenti, viene generata un'eccezione. Ad esempio, l'ultima riga del codice seguente genera un errore perché non esiste un attributo id nel secondo elemento p:

var doc:XML =  
            <body> 
                <p id='123'>Hello, <b>Bob</b>.</p> 
                <p>Hello.</p> 
            </body>; 
trace(doc.p.(@id == '123'));

Analogamente, l'ultima riga del codice seguente genera un errore perché non esiste una proprietà b del secondo elemento p:

var doc:XML =  
            <body> 
                <p id='123'>Hello, <b>Bob</b>.</p> 
                <p>Hello.</p> 
            </body>; 
trace(doc.p.(b == 'Bob'));

Per evitare questo tipo di errori, potete identificare le proprietà per cui esistono attributi o elementi corrispondenti usando i metodi attribute() e elements(), come nel codice seguente:

var doc:XML =  
            <body> 
                <p id='123'>Hello, <b>Bob</b>.</p> 
                <p>Hello.</p> 
            </body>; 
trace(doc.p.(attribute('id') == '123')); 
trace(doc.p.(elements('b') == 'Bob'));

Inoltre, potete utilizzare anche il metodo hasOwnProperty(), come nel codice seguente:

var doc:XML =  
            <body> 
                <p id='123'>Hello, <b>Bob</b>.</p> 
                <p>Hello.</p> 
            </body>; 
trace(doc.p.(hasOwnProperty('@id') && @id == '123')); 
trace(doc.p.(hasOwnProperty('b') && b == 'Bob'));

Uso delle istruzioni for..in e for each..in

ActionScript 3.0 comprende l'istruzione for..in e l'istruzione for each..in per l'iterazione negli oggetti XMLList. Osservate, ad esempio, il seguente oggetto XML, myXML, e l'oggetto XMLList, myXML.item. L'oggetto XMLList, myXML.item, è composto dai due nodi item dell'oggetto XML.

var myXML:XML =  
    <order> 
        <item id='1' quantity='2'> 
            <menuName>burger</menuName> 
            <price>3.95</price> 
        </item> 
        <item id='2' quantity='2'> 
            <menuName>fries</menuName> 
            <price>1.45</price> 
        </item> 
    </order>;

Il ciclo for..in permette di eseguire iterazioni su una serie di proprietà di un XMLList:

var total:Number = 0; 
for (var pname:String in myXML.item) 
{ 
    total += myXML.item.@quantity[pname] * myXML.item.price[pname]; 
}

Il ciclo for each..in permette di eseguire iterazioni sulle proprietà di XMLList:

var total2:Number = 0; 
for each (var prop:XML in myXML.item) 
{ 
    total2 += prop.@quantity * prop.price; 
}