「拡張JSONで表現したXMLの正規形」から引用:
正規形データに対して、DOM APIに相当するアクセス&操作の体系は簡単に定義できます。
「拡張JSONで表現したXMLの正規形」に沿った方法でやってみました。実際に簡単でした。
以下は、DOM APIの一部に相当する関数をPythonで書いたものです。elm.getAttribute(attr_name) のようなメソッドではなくて、getAttribute(elm, attr_name) のような関数形式です。また、ノード参照の代わりに配列インデックスを使っているところがあります。tag, tagged, untagged については後で少し説明します。
from caty.jsontools import tag, tagged, untagged def createElement(tag_name, obj={"": []}): return tagged(tag_name, obj) def tagName(elm): return tag(elm) def getAttribute(elm, attr_name): return untagged(elm)[attr_name] def hasAttribute(elm, attr_name): return attr_name in untagged(elm) def hasAttributes(elm): return len(untagged(elm)) > 1 def setAttribute(elm, attr_name, val): untagged(elm)[attr_name] = val def removeAttribute(elm, attr_name): del untagged(elm)[attr_nam] def childNodes(elm): return untagged(elm)[""] def hasChildNodes(elm): return len(untagged(elm)[""]) > 0 def firstChild(elm): return untagged(elm)[""][0] def lastChild(elm): return untagged(elm)[""][-1] def appendChild(elm, x): untagged(elm)[""].append(x) return x def insertBefore(elm, new, i): untagged(elm)[""].insert(i, new) return new def replaceChild(elm, new, i): untagged(elm)[""][i] = new return new def removeChild(elm, i): obj = untagged(elm) old = obj[""][i] del obj[""][i] return old
次の例を考えます。
<!-- HTMLインスタンス --> <a href="http://www.example.jp/">example <strong>JP domain</strong> site</a>
// XJSON(拡張JSON)インスタンス
@a {
"href" : "http://www.example.jp/",
"" : ["exmaple ", @strong {"" : ["JP domain"]}, " site"]
}
XJSON(拡張JSON)はアットマークで識別されたタグを持ちます。念のため、通常のJSONへのマーシャリング結果も示すと:
{
"$tag" : "a",
"href" : "http://www.example.jp/",
"" : ["exmaple ", {"$tag" : "strong", "" : ["JP domain"]}, " site"]
}
tagged("a", { "href" : "http://www.example.jp/", "" : ["exmaple ", tagged("strong", {"" : ["JP domain"]}), " site"] }
インスタンスのリテラル表現とほとんど変わりません。アットマーク表現 @tag data の代わりに tagged(tag, data) という関数呼び出しが使われるだけです。taggedで付加されたタグは tag(tagged_data) で取り出せます。タグ以外の部分は untagged(tagged_data) です。 tagとuntaggedは、タグが付いてないデータに対してもエラーではなくて合理的な動作をするようになっています。
XJSON(拡張JSON)のメモリ内の表現は非常にシンプルで、ノードの相対的関係をノード自体には保持していません。ですから、DOM APIの nextSibling, previousSibling, ownerDocument などは実現できません。しかし、SAX APIで出来る事なら、ツリーをルートからたどっていけば遂行できます。データ形式の変換などは、SAX風の処理でたいていは間に合いますね。
XMLをXJSON(拡張JSON)にエンコードする方法は、AjaxリクエストやWebAPIのレスポンスをJSON処理系に取り込むために考えたものです。しかし、しばらくいじっていると、これは軽量で単純ながらも一般的なXML処理にも使える気がしてきました。たとえば、文書処理とかにも。