Como percorrer estruturas XML

Flash Player 9 e posterior, Adobe AIR 1.0 e posterior

Um dos recursos avançados do XML é fornecer dados aninhados complexos por meio de uma string linear de caracteres de texto. Ao carregar dados em um objeto XML, o ActionScript analisa os dados e carrega sua estrutura hierárquica na memória (ou envia um erro de tempo de execução se os dados XML não estiverem bem formados).

Os operadores e métodos dos objetos XML e XMLList facilitam o percurso pela estrutura de dados XML.

Use o operador de dot (.) e o operador de acessador do descendente (..) para acessar as propriedades filho de um objeto XML. Considere o objeto XML a seguir:

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>

O objeto myXML.book é um objeto XMLList que contém as propriedades filhas do objeto myXML chamado book . Esses dois objetos XML correspondem às duas propriedades book do objeto myXML .

O objeto myXML..lastName é um objeto XMLList que contém todas as propriedades do descendente com o nome lastName . Esses dois objetos XML correspondem às duas propriedades lastName do objeto myXML .

O objeto myXML.book.editor.lastName é um objeto XMLList que contém todos os filhos com o nome lastName dos filhos com o nome editor dos filhos com o nome book do objeto myXML : nesse caso, um objeto XMLList que contém apenas um objeto XML (a propriedade lastName com o valor " Case ").

Acesso a nós pai e filho

O método parent() retorna o pai de um objeto XML.

Você pode usar os valores ordinais de índice de uma lista de filhos para acessar objetos filho específicos. Por exemplo, considere um objeto XML myXML que tem duas propriedades filho chamadas book . Cada propriedade filho chamada book tem um número de índice associado:

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

Para acessar um neto específico, você pode especificar números de índice para os nomes do filho e do neto:

myXML.book[0].title[0]

No entanto, se houver apenas um filho de x.book[0] com o nome title , você pode omitir a referência de índice do seguinte modo:

myXML.book[0].title

Do mesmo modo, se houver apenas um filho de book do objeto x , e se esse objeto filho tiver apenas um objeto title, você pode omitir as duas referências de índice assim:

myXML.book.title

É possível usar o método child() para navegar até os filhos com nomes baseados em uma variável ou expressão, como mostra o exemplo a seguir:

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

Acesso a atributos

Use o símbolo @ (operador de identificador de atributo) para acessar atributos em um objeto XML ou XMLList, como mostra o código a seguir:

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

Você pode usar o símbolo de caractere curinga * com o símbolo @ para acessar todos os atributos de um objeto XML ou XMLList, como no código a seguir:

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

Você pode usar o método attribute() ou attributes() para acessar um atributo específico ou todos os atributos de um objeto XML ou XMLList, como no código a seguir:

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

Também é possível usar a sintaxe a seguir para acessar atributos, como mostra o seguinte exemplo:

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

Cada um é equivalente a employee.@id . No entanto, a sintaxe employee.@id é recomendada.

Filtragem por valor de elemento ou atributo

Você pode usar os operadores de parênteses – ( e ) – para filtrar elementos com um nome de elemento ou valor de atributo específico. Considere o objeto XML a seguir:

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>

As seguintes expressões são válidas:

  • x.employee.(lastName == "McGee") – É o segundo nó employee .

  • x.employee.(lastName == "McGee").firstName – É a propriedade firstName do segundo nó employee .

  • x.employee.(lastName == "McGee").@id – É o valor do atributo id do segundo nó employee .

  • x.employee.(@id == 347) – O primeiro nó employee .

  • x.employee.(@id == 347).lastName – É a propriedade lastName do primeiro nó employee .

  • x.employee.(@id > 300) – É um XMLList com as duas propriedades employee .

  • x.employee.(position.toString().search("analyst") > -1) – É um objeto XMLList com as duas propriedades position .

Se você tentar filtrar os atributos ou elementos que não existem, é lançada uma exceção. Por exemplo, a linha final do código a seguir gera um erro, porque não existe nenhum atributo id no segundo elemento p :

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

Do mesmo modo, a linha final do código a seguir gera um erro, porque não existe nenhuma propriedade b do 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 esses erros, você pode identificar as propriedades que têm atributos ou elementos correspondentes usando os métodos attribute() e elements() , como no código a seguir:

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

Também é possível usar o método hasOwnProperty() , como no seguinte código:

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 for..in e for each..em instruções

O ActionScript 3.0 inclui a instrução for..in e a instrução for each..in para percorrer objetos XMLList. Por exemplo, considere o seguinte objeto XML, myXML , e o objeto XMLList, myXML.item . O objeto XMLList, myXML.item, consiste em dois nós item do 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>;

A instrução for..in permite percorrer um conjunto de nomes de propriedades em um XMLList:

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

A instrução for each..in permite percorrer as propriedades em um objeto XMLList:

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