XMLパーサー
Ajaxのリクエストは"XMLHttpRequest"というくらいで、返りはXMLでもらうのが正統的なようです。(埋め込みする内容であれば、サーバ側でHTMLかXHTMLにしてもらうのも楽で良いと思いますが)。従って、XMLパーサが標準装備されています。他の開発では、サーバからXMLで送り返していて、当初は適当に正規表現を使って読み出していたのだけど、数回読み直している(作りが適当)こともあり、パーサがあるのなら使うことにする。しかしながら、これを使うのは結構難しく感じたので、ポイントを解説してみます。
パーサーの使い方
Ajaxで使う際の基本的な手順は以下の通りであるが、DOMモデルということで、一般のJavaScriptでも同じことです。
まずオーバービューです。
受信物をXMLとして読みこむ。
xml = xmlhttp.responseXML;
childNodesやgetElementsByTagNameなどでアクセスする。
var urd = xml.getElementsByTagName("unread")[0].childNodes[0].nodeValue;
さて、以下のようなXML文書を読んでみる。
<?xml version="1.0"?>
<omail version="1.0">
<unread>488</unread>
<newmail>435</newmail>
<digest>
<mail from="brunhilde@fire.edu" subject="年々歳々花相似"/>
<mail from="wotan@walhara.com" subject="死もまた暗い"/>
<mail from="sigrinde@human.net" subject="生は暗く"/>
</digest>
</omail>
これを読むのは、こんな感じになる。一見して、すごく分り難いと思うのだけど。
Debug(xml.getElementsByTagName("unread")[0].nodeType); // 1
Debug(xml.getElementsByTagName("unread")[0].childNodes[0].nodeType); // 3
var urd = xml.getElementsByTagName("unread")[0].childNodes[0].nodeValue;
var nml = xml.getElementsByTagName("newmail")[0].childNodes[0].nodeValue;
drst.innerHTML = "<span class=\"strong\"><ul>"
+ "<li>unseen: " + urd + "</li>"
+ "<li>newmail: " + nml + "</li>"
+ "</ul></span>";
var mals = xml.getElementsByTagName("mail");
Debug(mals.length + "/" + mals.nodeType); // 3/1
for (i = 0; i < mals.length; i++) {
Debug("mail[" + i + "]: " + mals[i].getAttribute("from").substring(0,16));
Debug("mail[" + i + "]: " + mals[i].getAttribute("subject"));
}
基本的な考え方は、
- タグのネストを親子関係で管理している。(これはまぁ、こんなもんですか)
- Nodeが基本単位で、element(要素)、attribute(属性)、テキストなどがあり、nodeTypeで区別される。タグに挟まれたものの中身はnodeValue。
- 内包物は通常複数入ることが許されているので、配列で管理されている。
- TAG名などで検索した結果は、配列に格納される。
- コンビニエンスのために、firstChildみたいなのがある。
しかし、実際に何が何に当るかは、やってみないと良く分らない。オールドプログラマ的には、データ構造(structureのヘッダ)を見せてもらえば一発で理解できるような気が。複雑な構造は、単純にpropertyとmethodだけ見せられても、使い方が分らない。IFに隠されてしまうのも善し悪しですね。
ちなみにC#であれば、こんな感じになります。(動作は試していません)
Stream data = client.OpenRead(uri);
StreamReader reader = new StreamReader(data);
XmlReader xr = XmlReader.Create(reader);
while (xr.Read()) {
switch (xr.NodeType) {
case XmlNodeType.Element:
if (xr.LocalName == "unread") {
urd = xr.ReadString();
} else if (xr.LocalName == "newmail") {
nml = xr.ReadString();
} else if (xr.LocalName == "mail") {
Debug.WriteLine("from: " + xr.GetAttribute("from"));
Debug.WriteLine("from: " + xr.GetAttribute("subject"));
}
break;
default:
break;
}
}
xr.Close();
reader.Close();
data.Close();
ランダムアクセス系と、頭から読む系の違いがあります。(どちらの環境においても、どちらのポリシー向きのAPIは用意されているのでしょうが)。初心者には、頭から読むほうが理解し易いですね。実際、読み方にそれほど拘る必要はないと思われます。それは、通常、通信に掛かる時間のほうが桁違いに長いので、よほどのことがない限り、処理の重さが気になることはないでしょうから。
私の感想としては、XMLの利点は、文字列のエスケープを自動でしてくれること、ヒト可読性があること、読み書きルーチンが与えられていること、にあると思うのですが、汎用ルーチンのデータ構造が複雑になると、ソースを貰って自分で不要な部分を削って単純なものを作りたくなります。
API使って色々したいって時に、JavaScriptにてXMLのパースを初めてやってみたので、 ちょいメモメモ。 CDATAセクションの扱いとかも勉強になった。 XMLがこんな感じだったとする で、IDの中身の値 001 ...
Tracked: 4月 06, 21:09