XML 구조 순회

Flash Player 9 이상, Adobe AIR 1.0 이상

XML의 강력한 기능 중 하나는 선형 텍스트 문자열을 통해 복잡한 중첩 데이터를 제공하는 것입니다. 데이터를 XML 객체로 로드하면 ActionScript에서 해당 데이터를 파싱하고 계층 구조를 메모리로 로드합니다. 이때 XML 데이터 형식이 잘못된 경우에는 런타임 오류가 발생합니다.

XML 및 XMLList 객체의 연산자와 메서드를 사용하면 XML 데이터 구조를 쉽게 순회할 수 있습니다.

도트 (.) 연산자 및 자손 접근자(..) 연산자를 사용하면 XML 객체의 자식 속성에 액세스할 수 있습니다. 다음과 같은 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 객체는 이름이 bookmyXML 객체의 자식 속성을 포함하는 XMLList 객체입니다. 이러한 두 XML 객체는 myXML 객체의 두 book 속성에 대응됩니다.

myXML..lastName 객체는 이름이 lastName인 하위 속성을 포함하는 XMLList 객체입니다. 이러한 두 XML 객체는 myXML 객체의 두 lastName 속성에 대응됩니다.

myXML.book.editor.lastName 객체는 lastName이라는 자식 속성을 포함하는 XMLList 객체입니다. 여기에서 lastName은 editor의 자식 속성이며 editor는 book의 자식 속성입니다. 또한 book은 myXML 객체의 자식입니다. 이 예제의 경우에는XML 객체(값이 "Case"로 설정된 lastName 속성)를 하나만 포함하는 XMLList 객체입니다.

부모 및 자식 노드 액세스

parent() 메서드는 XML 객체의 부모를 반환합니다.

자식 목록의 서수 인덱스 값을 사용하여 특정 자식 객체에 액세스할 수 있습니다. 예를 들어 myXML이라는 XML 객체에 이름이 book인 자식 속성이 두 개 포함되어 있는 경우를 가정해 봅니다. 이때 각 자식 속성 book에는 인덱스 번호가 연결되어 있습니다.

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

특정 손자 항목에 액세스하려면 자식 이름과 손자 이름에 모두 인덱스 번호를 지정해야 합니다.

myXML.book[0].title[0]

그러나 이름이 titlex.book[0]의 자식이 하나뿐인 경우에는 다음과 같이 인덱스 참조를 생략할 수 있습니다.

myXML.book[0].title

마찬가지로 x 객체의 book 자식이 하나뿐이고 해당 자식 객체에 title 객체가 하나뿐인 경우에는 다음과 같이 두 인덱스 참조를 모두 생략할 수 있습니다.

myXML.book.title

다음 예제와 같이 child() 메서드를 사용하여 변수 또는 표현식을 기반으로 이름에 따라 자식 항목을 탐색할 수 있습니다.

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

특성 액세스

다음 코드와 같이 XML 또는 XMLList 객체에서 특성에 액세스하려면 @ 심볼(특성 식별자 연산자)을 사용합니다.

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

다음 코드와 같이 * 와일드카드 심볼을 @ 심볼과 함께 사용하면 XML 또는 XMLList 객체의 모든 특성에 액세스할 수 있습니다.

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

다음 코드와 같이 attribute() 또는 attributes() 메서드를 사용하면 XML 또는 XMLList 객체의 특정 특성이나 모든 특성에 액세스할 수 있습니다.

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

다음 예제와 같이 아래 구문을 사용하여 특성에 액세스할 수도 있습니다.

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

이러한 구문은 각각 employee.@id. employee.@id 구문을 사용하는 것이 좋습니다.

특성 또는 요소 값으로 필터링

괄호 연산자인 ()를 사용하면 특정 요소 이름 또는 특성 값으로 요소를 필터링할 수 있습니다. 다음과 같은 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>

다음 표현식은 모두 유효합니다.

  • x.employee.(lastName == "McGee") - 두 번째 employee 노드입니다.

  • x.employee.(lastName == "McGee").firstName - 두 번째 employee 노드의 firstName 속성입니다.

  • x.employee.(lastName == "McGee").@id - 두 번째 employee 노드의 id 특성 값입니다.

  • x.employee.(@id == 347) - 첫 번째 employee 노드입니다.

  • x.employee.(@id == 347).lastName - 첫 번째 employee 노드의 lastName 속성입니다.

  • x.employee.(@id > 300) - 두 employee 속성이 모두 포함된 XMLList입니다.

  • x.employee.(position.toString().search("analyst") > -1) - 두 position 속성이 모두 포함된 XMLList입니다.

존재하지 않는 특성 또는 요소를 필터링하려고 하면 예외가 발생합니다. 예를 들어 다음 코드의 경우 두 번째 p 요소에 id 특성이 없으므로 마지막 행에서 오류가 발생합니다.

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

마찬가지로 다음 코드에서도 두 번째 p 요소의 b 속성이 없으므로 마지막 줄에서 오류가 발생합니다.

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

이러한 오류가 발생하지 않게 하려면 다음 코드와 같이 attribute()elements() 메서드를 사용하여 대응하는 특성 또는 요소가 있는 속성을 식별해야 합니다.

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

다음 코드와 같이 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'));

for..in 및 for each..in 문 사용

ActionScript 3.0에는 XMLList 객체를 반복할 수 있도록 for..in 문과 for each..in 문이 포함되어 있습니다. 예를 들어 myXML이라는 XML 객체와 myXML.item이라는 XMLList 객체가 있다고 가정해 봅니다. 이때 XMLList 객체 myXML.item은 XML 객체의 두 item 노드로 구성되어 있습니다.

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

for..in 문을 사용하면 XMLList의 속성 이름 집합을 반복할 수 있습니다.

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

for each..in 문을 사용하면 XMLList의 속성을 반복할 수 있습니다.

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