Navegación de estructuras XML

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

Una de las eficaces características de XML es su capacidad de proporcionar datos complejos y anidados a través de una cadena lineal de caracteres de texto. Al cargar datos en un objeto XML, ActionScript analiza los datos y carga su estructura jerárquica en memoria (o envía un error en tiempo de ejecución si los datos XML no están bien formados).

Los operadores y métodos de los datos XML y objetos XMLList facilitan la navegación de la estructura de datos XML.

El operador punto (.) y el operador descriptor de acceso descendente (..) permiten acceder a propiedades secundarias de un objeto XML. Considere el siguiente objeto XML:

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>

El objeto myXML.book es un objeto XMLList que contiene propiedades secundarias del objeto myXML denominado book . Son dos objetos XML, que coinciden con las dos propiedades book del objeto myXML .

El objeto myXML..lastName es un objeto XMLList que contiene todas las propiedades de descendentes denominadas lastName . Son dos objetos XML, que coinciden con las dos propiedades lastName del objeto myXML .

El objeto myXML.book.editor.lastName es un objeto XMLList que contiene los elementos secundarios que tengan el nombre lastName de los elementos secundarios denominados editor de los elementos secundarios llamados book del objeto myXML : en este caso, es un objeto XMLList que contiene solo un objeto XML (la propiedad lastName con el valor " Case ").

Acceso a nodos principales y secundarios

El método parent() devuelve el elemento principal de un objeto XML.

Se pueden utilizar los valores de índice ordinales de una lista secundaria para acceder a objetos secundarios específicos. Por ejemplo, considérese un objeto XML myXML que tiene dos propiedades secundarias denominadas book . Cada propiedad secundaria denominada book tiene un número de índice asociado:

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

Para acceder a un elemento terciario específico se pueden especificar números de índice para los nombres del elemento secundario y el elemento terciario:

myXML.book[0].title[0]

Sin embargo, si x.book[0] solo tuviera un elemento secundario denominado title , se puede omitir la referencia al índice, como se muestra a continuación:

myXML.book[0].title

De forma similar, si solo hay un elemento secundario book del objeto x y dicho objeto secundario tiene un solo objeto de título, se pueden omitir ambas referencias de índice, como se muestra a continuación:

myXML.book.title

Se puede utilizar el método child() para desplazarse por los elementos secundarios con nombres basados en una variable o expresión, como se indica en el siguiente ejemplo:

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

Acceso a atributos

El símbolo @ (el operador identificador de atributo) se utiliza para acceder a atributos de un objeto XML o XMLList, como se muestra en el código siguiente:

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

Se puede utilizar el símbolo de comodín * con el símbolo @ para acceder a todos los atributos de un objeto XML o XMLList, como se muestra en el código siguiente:

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

Se puede utilizar el método attribute() o attributes() para acceder a un atributo específico o a todos los atributos de un objeto XML o XMLList, como se muestra en el código siguiente:

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

También se puede utilizar la sintaxis siguiente para acceder a atributos, como se muestra en el siguiente ejemplo:

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

Todos ellos equivalen a employee.@id . Sin embargo, la sintaxis employee.@id es la preferida.

Filtrado por atributo o valor de elemento

Se pueden utilizar los operadores de paréntesis, ( y ) , para filtrar elementos con un nombre de elemento o un valor de atributo específicos. Considere el siguiente objeto XML:

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>

Las siguientes expresiones son todas válidas:

  • x.employee.(lastName == "McGee") ; es el segundo nodo employee .

  • x.employee.(lastName == "McGee").firstName ; es la propiedad firstName del segundo nodo employee .

  • x.employee.(lastName == "McGee").@id ; es el valor del atributo id del segundo nodo employee .

  • x.employee.(@id == 347) ; es el primer nodo employee .

  • x.employee.(@id== 347).lastName ; es la propiedad lastName del primer nodo employee .

  • x.employee.(@id > 300) ; es un objeto XMLList con ambas propiedades employee .

  • x.employee.(position.toString().search("analyst") > -1) ; es un objeto XMLList con ambas propiedades position .

Si se intentan filtrar atributos o elementos que no existen, se emitirá una excepción. Por ejemplo, la línea final del código siguiente genera un error porque no hay ningún atributo id en el segundo elemento p :

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

De manera similar, la línea final del código siguiente genera un error porque no hay ningún atributo b en el segundo elemento p :

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

Para evitar estos errores, se pueden identificar las propiedades que tienen los atributos o elementos coincidentes mediante los métodos attribute() y elements() , como se muestra en el código siguiente:

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

También se puede utilizar el método hasOwnProperty() , como se muestra en el código siguiente:

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 de las sentencias for..in y for each..in

ActionScript 3.0 incluye las sentencias for..in y for each..in para recorrer los objetos XMLList. Por ejemplo, considérese el objeto XML myXML y el objeto XMLList myXML.item . El objeto XMLList, myXML.item , consta de los dos nodos item del objeto 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>;

El bucle for..in permite recorrer un conjunto de nombres de propiedad de un objeto XMLList:

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

El bucle for each..in permite recorrer las propiedades del objeto XMLList:

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