ネット検索でよく見かける方法では、XMLタグ名にコロン(名前空間)や属性が含まれる場合には、JSON化した時に抜け落ちます。(ただし、PHPのバージョンにかなり依存するようです)
例)以下をJSON化すると「コロンを含んだ名前空間タグ」「属性名="属性値"」「CDATA」がごっそり消えてしまいます…
xml
<root>
<test1:abc>値1</test1:abc>
<test2 属性名="属性値">値2</test2>
<test3><![CDATA[値3]]></test3>
</root>
json
{
"test2": "値2",
"test3": {},
}
なお、環境は PHP5.4 です。 (JSON_XXX定数を使わなければPHP5.3でも動作可)
サンプルコード
以下、急場しのぎ的な部分もありますが、『XML⇒JSON変換』関数を自作してみました。
php
// XML(RSSなど)を取得
$strXml = file_get_contents("http://xxx.com/rss");
// XML⇒JSONに変換
$strJson = xml_to_json($strXml);
// 出力
echo $strJson;
//**********************************
// XML ⇒ JSONに変換する関数
//**********************************
function xml_to_json($xml)
{
// コロンをアンダーバーに(名前空間対策)
$xml = preg_replace("/<([^>]+?):([^>]+?)>/", "<$1_$2>", $xml);
// プロトコルのは元に戻す
$xml = preg_replace("/_\/\//", "://", $xml);
// XML文字列をオブジェクトに変換(CDATAも対象とする)
$objXml = simplexml_load_string($xml, NULL, LIBXML_NOCDATA);
// 属性を展開する
xml_expand_attributes($objXml);
// JSON形式の文字列に変換
$json = json_encode($objXml, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
// "\/" ⇒ "/" に置換
return preg_replace('/\\\\\//', '/', $json);
}
//**********************************
// XMLタグの属性を展開する関数
//**********************************
function xml_expand_attributes($node)
{
if($node->count() > 0) {
foreach($node->children() as $child)
{
foreach($child->attributes() as $key => $val) {
$node->addChild($child->getName()."@".$key, $val);
}
xml_expand_attributes($child); // 再帰呼出
}
}
}
※ソース内の json_encode() 関数の第2引数にある JSON_XXX の定数は、PHP5.4.0以降でしか使えませんのでご注意下さい
上記を実行すると、たとえばこういうXMLが、
xml
<root>
<test1:abc>値1</test1:abc>
<test2 属性名="属性値">値2</test2>
<test3><![CDATA[値3]]></test3>
</root>
こういうJSONに変換されます。
json
{
"test1_abc": "値1",
"test2": "値2",
"test3": "値3",
"test2@属性名": "属性値"
}
解説
- 名前空間については、コロンをアンダーバーに置換することで対応
- 属性については、親要素の子要素となる形で外出しすることで対応
- CDATAについては、
simplexml_load_string()
関数の第3引数にLIBXML_NOCDATA
を指定すればOK
(・o・ゞ いじょー。