XMLHttpRequest のプロパティ responseXML で XML が取得できるはずが、ブラウザによって値が入っていなかったり、IE においては for in でオブジェクトを走査できなかったりとなんだか面倒なことが多い。
逆にすべてのテキストとして取得する responseText はどのブラウザでもきちんと同じ文字列が入ってくるので、安心感がある。responseXML をごにょごにょするのにも疲れたので、responseText を JSON に変換して気軽に使ってしまおう!ということで、記録しておく。
ちなみにこの同じような処理は JKL.ParseXML というライブラリでできるのだが、こちらは文字列からのパースができないっぽい(URL を渡してリクエストしてくれる。Ajax.Request が内包されている感じ。)
XML 文字列から JSON に変換する例としては こちら にソースコードが掲載されている。これは空タグのときに null になるので、その部分を改修した。(本来の XML から言えば空タグ=子要素なし、だろうが、文字列として扱う場合に null だとそのまま "null" と表示されてしまうため、不便である。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
function XMLToJSON(ajax)
{
if (window.ActiveXObject)
{
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(ajax.responseText);
}
else if (window.DOMParser)
{
var xmlDoc = new DOMParser().parseFromString(
ajax.responseText,
"application/xml"
);
}
else
{
return;
}
var loopParse = function(obj)
{
var res = {}, cacheTag = {};
var ob = {}, att = obj.attributes;
if (att != null && att.length != 0)
{
for (var a = 0, lenA = att.length; a < lenA; a++)
{
ob[att[a].nodeName.toLowerCase()] = att[a].nodeValue;
}
res._attr = ob;
}
if (obj.childNodes.length > 0)
{
for (var i = 0, len = obj.childNodes.length; i < len; i++)
{
var ch = obj.childNodes[i];
if (ch.nodeType == 3)
{
if (ch.nodeValue.replace(/[\s|\t|\n]/g, "") == "" ||
ch.nodeValue == null) continue;
else return ch.nodeValue;
}
else if (ch.nodeType == 1)
{
(ch.tagName in cacheTag) ?
cacheTag[ch.tagName].push(arguments.callee(ch)) :
cacheTag[ch.tagName] = [arguments.callee(ch)];
}
}
}
else
{
return "";
}
for (var p in cacheTag)
{
(cacheTag[p].constructor == Array && cacheTag[p].length == 1) ?
res[p] = cacheTag[p][0] : res[p] = cacheTag[p];
}
return res;
}
return loopParse(xmlDoc);
}
引数 ajax には Ajax.Response などで生成された XMLHttpResponse を渡す。
たとえば responseText の内容が下記の XML だったとすると、
<?xml version="1.0" encoding="UTF-8"?> <persons> <person no="1"> <name>太郎</name> <age>15</age> </person> <person no="2"> <name>花子</name> <age>10</age> </person> </persons>
下記の一行で JSON にパースできる。
var data = XMLToJSON(xhr);
変換できたかどうかは data が null か、あるいは data.persons が undefined かどうかを調べればよい。以上で、
なお、この例ではたとえば person タグが 1 つしか存在しなかった場合は、配列にならず data.persons.person.name のようにアクセスすることになるので、注意が必要である。
Kenz Yamada(山田研二)。1984年生。大阪。ちょっとずつ好きなプログラム作ってます。
好きなものはカメラと旅行。ガジェットや身の回り、ちょっとこだわります。
詳しくは Web mixi で。