「XMLからJSONへの変換はこうすべ -- eXtendedJSON-encoded XML」において、拡張JSON(eXtended JSON or XJSON)にエンコードされたXMLの正規形を定義したのですが、どうもアレはよろしくない。一番短い形を正規形にするんじゃなくて、一番扱いやすい形を正規形にすべきでした。長いほうがむしろ扱いやすいですもんね。
まず、次の定義をします。
type NEString = string(minLength=1); // 非空文字列// 再帰的な定義
type Content = [(NEString | Element)*];
type Element = {
"" : Content, // 内容は必ず存在する
* : string? // その他のプロパティは属性を表す
};
これはほぼ正規形です。次の手続きを適用すると完全な正規形になります。
- 内容を表すリスト内で、隣り合う文字列は連結する。
上の正規化の手続きはDOM正規化とまったく同じです。@greeting {"": ["Hello, ", "world\n"]} は正規形ではありませんが、@greeting {"": ["Hello, world\n"]} は正規形です。
許容できる構文は次くらいでしょう(以前と同じ、再掲)。上で定義した正規形の型と区別するため、型名のお尻にXを付けています。
// 再帰的な定義
type BasicContentX = NEString | ElementX;
type ContentX = BasicContentX | [BasicContentX*];
type AttrCon = {"" : ContentX?, * : string?}; // 属性が付くかも知れない内容
type ElementX = @* AttrCon;
正規化の例を挙げます。「短縮形 ⇒ 正規形」です。
- @smile [] ⇒ @smile {"" : []}
- @smile {} ⇒ @smile {"" : []}
- @greeting ["Hello", @smile {}] ⇒ @greeting {"" : ["Hello", @smile {"": []}]}
- @greeting @smile [] ⇒ @greeting {"" : [@smile {"": []}]}
- @script {"src" : "js/lib.js"} ⇒ @script {"src" : "js/lib.js", "" :[]}
- @greeting ["hello, world.\n"] ⇒ @greeting {"" : ["hello, world.\n"]}
- @title "Webを支える技術" ⇒ @title {"" : ["Webを支える技術"]}
人が手で書いたり、コンソール画面に表示したりするには、非正規な短縮形(ショートハンド)が便利ですが、メモリ内に保存して操作するには今定義した正規形が便利です。正規形データに対して、DOM APIに相当するアクセス&操作の体系は簡単に定義できます。