E4Xとは

「ECMAScript for XML」の略。
ECMAScript3 の拡張として開発された XML データを扱うための仕様。
AS3では新しくE4Xのクラスがサポートされとります。

XMLデータへのアクセス

E4Xでは.や@でノードや属性にアクセス可能。

<order> 
  <book id="1"> 
    <title>learning AS3</title> 
  </book> 
</order> 

というデータが my_xml:XML に格納されている時、

trace(my_xml.book.title); // learning AS3
trace(my_xml.bool@id);    // 1

更新も同様に可能。

my_xml.book.title = "learning Flex";
my_xml.book@id = "2";

XMLデータの初期化

[](配列)や{}(オブジェクト)と同様にリテラル扱いあり。

xml:XML = <order>
   <book id="1">
      <title>learning AS3</title>
   </book>
</order>

っていう書き方があり。(代入しているのは文字列じゃないよ!ってこと)

{}で囲んでEL式チックな書き方も可能。

var attrName :String = "id";
var attrVal  :String = "3";
var tagName  :String = "title";
var content  :String = "learning AS3";
var xml:XML = <order>
   <book {attrName}={attrVal}>
      <{tagName}>{content}</{tagName}>
   </book>
</order>

XMLコンストラクタの場合は文字列もあり。

var xmlStr :String = "<order><book id="1"><title>learning AS3</title></book></order>";
var xml:XML = new XML(xmlStr);

E4Xなクラス

E4Xなクラスはトップレベル。

XML

XMLを表す。XMLのコレクションがXMLList。
コレクションが一つのXMLListはXMLと同じメソッドが使用可能なよう。

ノード・属性へのアクセス

メソッドよりも「.」「..」「@」でアクセスするほうが楽そう。

.子ノードへアクセス
..子孫ノードへアクセス
@属性へアクセス

アクセスの結果、候補が複数ある場合はXMLListが返ってくると思えばよいっぽい。

var employees:XML =
   <employees>
      <employee ssn="123-123-1234">
         <name first="John" last="Doe"/>
         <address>
            <street>11 Main St.</street>
            <city>San Francisco</city>
            <state>CA</state>
            <zip>98765</zip>
         </address>
      </employee>
      <employee ssn="789-789-7890">
         <name first="Mary" last="Roe"/>
         <address>
            <street>99 Broad St.</street>
            <city>Newton</city>
            <state>MA</state>
            <zip>01234</zip>
         </address>
      </employee>
   </employees>;

上記のようなXMLに対して以下操作。

trace(employees.employee.name); // <name first="John" last="Doe"/>
                                // <name first="Mary" last="Roe"/>
trace(employees..zip[0]);       // 98765
trace(employees..@ssn[1]);      // 789-789-7890

ワイルドカードも使える!

trace(employees.employee[0].address.*); // <street>11 Main St.</street>    
                                        // <city>San Francisco</city>
                                        // <state>CA</state>
                                        // <zip>98765</zip>

変数も絡めることができる。

var node:String = "zip";
trace(employees.employee[0].address[node]); // 98765

イテレートも完備。

for each (var num:XML in employees..@ssn) {
    trace(num);                             // 123-123-1234
}                                           // 789-789-7890

条件式キター!

var ssnToFind:String = "789-789-7890";
trace(employees.employee.(@ssn == ssnToFind).toXMLString()); // <employee ssn="789-789-7890">
                                                             // <name first="Mary" last="Roe"/>
                                                             // <address>
                                                             // <street>99 Broad St.</street>
                                                             // <city>Newton</city>
                                                             // <state>MA</state>
                                                             // <zip>01234</zip>
                                                             // </address>
                                                             // </employee>

XML変数から特定タグをごっそり取得

前述の例でzipタグを全部いくと以下。

employees..zip

toString

  • 単純内容の場合(子ノードがテキストノードオンリー)、String
  • 複合内容の場合、XML オブジェクト全体を表す XML エンコードされた String

toXMLString

常に XML オブジェクト全体を表す XML エンコードされた String。

XMLList

XMLのコレクション。
要素数が1つならXMLと同じ扱い。
個々の要素へは配列と同様[]を使用してアクセス。

employees.employee[0].name

length()

要素数を返すメソッド。配列と違ってプロパティじゃないとこがミソ。

Namespace

名前空間を定義して操作するためのメソッドとプロパティを持っている。
Namespaceをnewして、

private var rss:Namespace = new Namespace("http://purl.org/rss/1.0/");

ディレクティブで設定!

default xml namespace = rss

この記述でXMLオブジェクトに使用するデフォルトの名前空間を設定。
E4Xでは名前空間が指定されたXMLの解析は必ず正確に取り扱う必要がある。

QName

XMLエレメントの完全修飾名と属性を表す。
名前空間とかprefixとかの話だと思う、たぶん。

CDATAセクションを含むXMLデータを作成する

XML文字列を生成したい場合、XMLオブジェクトを生成→e4xでダイナミックにプロパティ設定→toXMLStringメソッドってな感じが簡単。

var rss:XML = <rss version="2.0" />;
xml.channel.title = "l4l";xml.channel.link = "http://kozy.heteml.jp/l4l/";
trace(xml.toXMLString());
//<rss version="2.0>
//   <channel>
//      <title>l4l</title>
//      <link>http://kozy.heteml.jp/l4l/</link>
//   </channel>
//</rss>

ただしこの方法の場合、<や>は参照文字<や>に変換される。プラスしてXMLクラスにはCDATAを作成するようなプロパティ、メソッドが見当たらない。というわけでCDATAを含めたい時にひとすじなわではいかない。

var rss:XML = <rss version="2.0" />;
xml.channel.title = "<![CDATA[<b>l4l</b>]]>";
xml.channel.link = "http://kozy.heteml.jp/l4l/";
trace(xml.toXMLString());
//<rss version="2.0>
//   <channel>
//      <title>&lt;![CDATA[&lt;b&gt;l4l&lt;/b&gt;]]&gt;</title>
//      <link>http://kozy.heteml.jp/l4l/</link>
//   </channel>
//</rss>

そんな時は文字列からXMLオブジェクト生成すればよい。

var rss:XML = <rss version="2.0" />;
xml.channel.title = new XML("<title><![CDATA[<b>l4l</b>]]></title>");
xml.channel.link = "http://kozy.heteml.jp/l4l/";trace(xml.toXMLString());
//<rss version="2.0>
//   <channel>
//      <title><![CDATA[<b>l4l</b>]]></title>
//      <link>http://kozy.heteml.jp/l4l/</link>
//   </channel>
//</rss>

エレメント追加はXMLオブジェクト作成→appendChildメソッドで追加でもいいはず。あくまでe4xな感じでやるならこんなとこ。