Еще если сложно разобраться с работой
E4X, то есть аналогичная реализация с помощью методов, по которым можно узнать что они возвращают XML или XMLList

Код AS3:
var xml:XML = new XML("<TEST/>");
xml.appendChild(new XML("<lvl1/>"));
xml.child("lvl1").appendChild(new XML("<lvl2/>")); //xml.lvl1.appendChild(<lvl2/>)
xml.child("lvl1").appendChild(new XML("<lvl2/>"));
Но использование E4X предпочтительнее, потому что работает быстрее
Резюмирую все что нужно помнить:
XMLList это промежуточный временный объект, который создается при обращении к любым вложенным элементам XML (будь-то атрибут, другая нода или текстовое содержимое). Если XMLList содержит один элемент, то обращение к методам и свойствам будет таким же как будто обращение идет к методам и свойствам этого элемента
пруф, это сделано для удобства чтоб не писать постоянно [0] в примитивных случаях например:

Код AS3:
var xml:XML = <xml><c><d>3</d></c></xml>;
xml.@a = "1";
xml.b = "2";
var a:String = xml.@a;
var b:String = xml.b;
var d:String = xml.c.d;
//эквивалентно
var xml:XML = <xml><c><d>3</d></c></xml>;
xml.@a[0] = "1";
xml.b[0] = "2";
var a:String = xml.@a[0];
var b:String = xml.b[0];
var d:String = xml.c[0].d[0];
Если идет обращение к несуществующему элементу, то создается пустой XMLList.
А если выполнить присвоение, то несуществующие элементы создадутся

Код AS3:
var xml:XML = <xml/>;
xml.c1.ch2.ch3.* = <a b="1"/>; //<xml><c1><ch2><ch3><a b="1"/></ch3></ch2></c1></xml>
Содержимое в виде текста также является элементом XMLList под 0 индексом

Код AS3:
var xml:XML = <xml>123</xml>;
xml.*[0] = 321; //<xml>321</xml>
В целом при обращении к API XML все возвращает XMLList в котором может быть XML,XMLList,String
Чтобы удостовериться что XMLList каждый раз создается и содержит ссылки (даже на parent) можно провести такой опыт:

Код AS3:
var xml:XML = <xml><c><d></d></c></xml>;
var d1:XMLList = xml.c.d;
var d2:XMLList = xml.c.d;
trace(d1 === d2); //false
d1.appendChild(<a>1</a>);
trace(d2.toXMLString()); //<d><a>1</a></d>