MEXSLT

XSLTのMXMLを書く事でXMLParserを作ることができます

きっと、AS3で書くよりも分かりやすいソースコードにならないかと思ったんです

コード

必須ライブラリ

MEXSLTは以下のライブラリを使用しています

使い方

まずこんなXMLを読み込むとしましょう

<?xml version="1.0" encoding="UTF-8"?>
<records>
	<record>
		<name>宇多田 信輔</name>
		<ruby>うただ しんすけ</ruby>
		<mail>utada_shinsuke@example.com</mail>
		<sex>男</sex>
		<age>65</age>
		<birthday>1944/1/1</birthday>
		<married>既婚</married>
		<bloodtype>A型</bloodtype>
		<prefecture>埼玉県</prefecture>
		<curry>ぶっかけ・せき止め派</curry>
	</record>
	<record>
		<name>竹下 未來</name>
		<ruby>たけした みらい</ruby>
		<mail>takeshita_mirai@example.com</mail>
		<sex>男</sex>
		<age>24</age>
		<birthday>1984/10/12</birthday>
		<married>既婚</married>
		<bloodtype>A型</bloodtype>
		<prefecture>新潟県</prefecture>
		<curry>ぶっかけ・せき止め派</curry>
	</record>
	<record>
		<name>北村 翔太</name>
		<ruby>きたむら しょうた</ruby>
		<mail>kitamura_shouta@example.com</mail>
		<sex>男</sex>
		<age>37</age>
		<birthday>1972/1/8</birthday>
		<married>既婚</married>
		<bloodtype>O型</bloodtype>
		<prefecture>神奈川県</prefecture>
		<curry>手前ルー・せき止め派</curry>
	</record>
	...
</records>

このXMLを解析して、こんなクラスに情報を格納したいとします

package me.rkome.da.sample.model
{
	public class DummyData
	{
		public function DummyData()
		{
		}

		public var name:String;
		public var ruby:String;
		public var mail:String;
		public var sex:String;
		public var age:Number;
		public var birthday:Date;
		public var married:Boolean;
		public var bloodType:String;
		public var prefecture:String;
		public var curry:String;
		
		public function setBirthday(dateString:String):void
		{
			var array:Array = dateString.split("/");
			birthday = new Date(parseInt(array[0]), parseInt(array[1]), parseInt(array[2]));
		}
		
		public function setMarried(marriedString:String):void
		{
			married = (marriedString == "既婚");
		}
		
		public function toString():String
		{
			return "名前: " + this.name + "\n" +
					"よみ: " + this.ruby + "\n" +
					"メール: " + this.mail + "\n" +
					"性別: " + this.sex + "\n" +
					"歳: " + (this.sex == "女" ? this.age - 2 : this.age) + "\n" +
					"生年月日: " + this.birthday.toDateString() + "\n" +
					"結婚: " + (this.sex == "女" && !this.married && 30 <= this.age ? "募集中" : this.married) + "\n" +
					"血液型: " + this.bloodType + "\n" +
					"出身: " + this.prefecture + "\n" +
					"カレーの食べ方: " + this.curry;
		}
	}
}

生年月日はDate型、結婚しているかどうかはBoolean型となっています
このクラスの配列を読み込み結果として返してくれるXMLParserをMEXSLTを用いて書くと、こんな風に書けます

<mex:MEXSLT id="parser" output="array">
	<mex:xslt>
		<mex:Template match="records/record">
			<mex:New method="push" product="{DummyData}">
				<mex:ValueOf select="name" target="name" />
				<mex:ValueOf select="ruby" target="ruby" />
				<mex:ValueOf select="mail" target="mail" />
				<mex:ValueOf select="sex" target="sex" />
				<mex:ValueOf select="age" target="age" />
				<mex:ValueOf select="birthday" target="setBirthday" method="invoke" />
				<mex:ValueOf select="married" target="setMarried" method="invoke" />
				<mex:ValueOf select="bloodtype" target="bloodType" />
				<mex:ValueOf select="prefecture" target="prefecture" />
				<mex:ValueOf select="curry" target="curry" />
			</mex:New>
		</mex:Template>
	</mex:xslt>
</mex:MEXSLT>

MEXSLTタグ

MEXSLTタグのoutput属性に結果を返すデータ形式をarray、objectのどちらかを指定します
そして、MEXSLTタグのxsltプロパティにXMLを解析するルールを記述します

Templateタグ

Templateタグを使ってターゲットとするXMLタグの指定をmatch属性にXPathを使って記述します
サンプルの場合だと『records/record』と書いているので、<records>の子の<record>を対象とするよう指定しています

Newタグ

次に、指定したXMLタグをどんなクラスオブジェクトに変換するかをNewタグを使って指定します
method属性には、assign・push・invokeのいずれかを指定します

  • pushの場合、生成されたオブジェクトは出力配列にpushされます
  • assignの場合、生成されたオブジェクトは出力オブジェクトのtarget属性で指定したプロパティに設定されます
  • invokeの場合、target属性で指定した文字列を関数名として認識して、生成されたオブジェクトを引数に渡して関数を呼び出します

サンプルでは、MEXSLTタグにoutput属性を設定しているので、methodにはpushを指定しています
これで生成されたDummyData?クラスのインスタンスは出力配列に追加されます

product属性には生成するクラスを指定します

ValueOf?タグ

そして、<record>の中身をValueOf?タグを使ってNewタグが生成するオブジェクトに代入します

  • select属性にXPathで代入する子要素、属性名を指定します
  • target属性に代入先のプロパティ名、または関数名を指定します
  • method属性に設定方法(assign、push、invoke)を設定します
  • required属性にtrueを設定すると、select属性で指定した要素が読み込んだXMLにない場合に解析エラーを投げるようになります
  • defaultValue属性に値を設定する事で、select属性で指定した要素が読み込んだXMLにない場合にデフォルトの値を設定するようになります

こうして出来たXMLParserは、こんな感じに使うことで、XML読み込みを行います

var xml:String = "<records>さっきのXML...</records>";
var result:Array = parser.parse(new XML(xml));
for each (var data:DummyData in result)
{
	println(data.toString());
	println("================================");
}

required属性を指定している場合は、XML解析エラーを投げることがあるので、try-catchで例外処理を書いてください

ここで説明したサンプルはas3/MEXSLT/MEXSLTSampleにいれてあります
実際の動作は、しばらくはそちらで確認してください

ライセンス

つくったひと

darkomeme (d [あっと] rkome.me) blog

TODO

  • サンプルを掲載する