Przeglądanie struktur XML

Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje

Jedną z największych zalet języka XML jest możliwość odzwierciedlenia złożonych, zagnieżdżonych struktur danych w postaci liniowego ciągu znaków tekstowych. Podczas ładowania danych do obiektu XML środowisko ActionScript analizuje te dane i umieszcza ich hierarchiczną strukturę w pamięci (lub zgłasza błąd, jeśli dane XML nie są poprawnie sformatowane).

Operatory i metody obiektów XML oraz XMLList ułatwiają programowe przeglądanie struktury danych XML.

Kropka (.) oraz akcesor węzła podrzędnego (..) umożliwiają dostęp do właściwości podrzędnych obiektu XML. Rozważmy następujący obiekt 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>

myXML.book to obiekt XMLList zawierający właściwości podrzędne obiektu myXML o nazwie book . Są to dwa obiekty XML, odpowiadające dwóm właściwościom book obiektu myXML .

myXML..lastName to obiekt XMLList zawierający wszystkie elementy podrzędne o nazwie lastName . Są to dwa obiekty XML odpowiadające dwóm właściwościom lastName obiektu myXML .

myXML.book.editor.lastName to obiekt XMLList zawierający wszystkie elementy podrzędne o nazwie lastName elementów podrzędnych o nazwie editor elementów podrzędnych o nazwie book obiektu myXML : w tym przypadku obiekt XMLList zawierający tylko jeden obiekt XML (właściwość lastName o wartości " Case ").

Dostęp do węzłów nadrzędnych i podrzędnych

Metoda parent() zwraca obiekt nadrzędny danego obiektu XML.

Do konkretnych obiektów podrzędnych można odwoływać się poprzez ich numery kolejne na liście obiektów podrzędnych. Rozważmy na przykład obiekt XML myXML , który ma dwie właściwości podrzędne o nazwie book . Każda właściwość podrzędna o nazwie book ma przypisany numer (indeks):

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

Aby odwołać się do obiektu podrzędnego o dwa poziomy niżej (do „wnuka”), należy określić indeksy zarówno obiektu podrzędnego (pierwszy poziom), jak i jego obiektu podrzędnego (drugi poziom).

myXML.book[0].title[0]

Jeśli jednak istnieje tylko jeden obiekt podrzędny obiektu x.book[0] o nazwie title , można pominąć indeks:

myXML.book[0].title

Podobnie, jeśli istnieje tylko jeden element podrzędny book obiektu x , i jeśli ten obiekt podrzędny ma tylko jeden obiekt title, można pominąć oba indeksy:

myXML.book.title

Metoda child() umożliwia przechodzenie do elementów podrzędnych o nazwach określonych jako wartość zmiennej lub wyrażenia, co ilustruje następujący przykład:

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

Dostęp do atrybutów

Symbol @ (identyfikator atrybutu) umożliwia dostęp do atrybutów w obiekcie XML lub XMLList, co ilustruje następujący przykład:

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

Symbol wieloznaczny * oraz symbol @ umożliwiają dostęp do wszystkich atrybutów obiektu XML lub XMLList, co zilustrowano poniżej:

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

Z kolei metody attribute() oraz attributes() pozwalają na dostęp do konkretnego atrybutu lub wszystkich atrybutów obiektu XML lub XMLList, tak jak widzimy poniżej:

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

Należy zwrócić uwagę, że dostęp do atrybutów jest możliwy przy użyciu także następującej składni:

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

Wszystkie zapisy są równoważne employee.@id . Jednak składnia employee.@id jest preferowana.

Filtrowanie według wartości atrybutów lub elementów

Operatory nawiasów — ( oraz ) — umożliwiają filtrowanie elementów na podstawie nazwy lub wartości atrybutu: Rozważmy następujący obiekt 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>

Wszystkie poniższe wyrażenia są poprawne:

  • x.employee.(lastName == "McGee") — to jest drugi węzeł employee .

  • x.employee.(lastName == "McGee").firstName — to jest właściwość firstName drugiego węzła employee .

  • x.employee.(lastName == "McGee").@id — to jest wartość atrybutu id drugiego węzła employee .

  • x.employee.(@id == 347) — pierwszy węzeł employee .

  • x.employee.(@id == 347).lastName — to jest właściwość lastName pierwszego węzła employee .

  • x.employee.(@id > 300) — to jest obiekt XMLList z obiema właściwościami employee .

  • x.employee.(position.toString().search("analyst") > -1) — to jest obiekt XMLList z obiema właściwościami position .

Próba filtrowania na podstawie nieistniejących atrybutów lub elementów spowoduje wygenerowanie wyjątku. Na przykład ostatni wiersz poniższego kodu wywoła błąd, ponieważ nie istnieje atrybut id w drugim elemencie p :

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

Podobnie ostatni wiersz poniższego kodu wywoła błąd, ponieważ nie istnieje właściwość b drugiego elementu p :

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

Aby uniknąć tych błędów, można zidentyfikować właściwości ze zgodnymi atrybutami elementami, korzystając z metod attribute() i elements() , tak jak w poniższym kodzie:

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

Możliwe jest także użycie metody hasOwnProperty() :

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

Korzystanie z instrukcji for..in oraz for each..in

Język ActionScript 3.0 zawiera instrukcję for..in oraz instrukcję for each..in , które umożliwiają iteracyjne przeglądanie obiektów XMLList. Rozważmy na przykład następujący obiekt XML, myXML , oraz obiekt XMLList myXML.item . Obiekt XMLList myXML.item zawiera dwa węzły item obiektu 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>;

Pętla for..in umożliwia iteracyjne przeglądanie zbioru nazw właściwości w obiekcie XMLList:

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

Pętla for each..in umożliwia iteracyjne przeglądanie właściwości w obiekcie XMLList:

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