simpleXMLはnamespaceに注意
simpleXML関数が便利、ということを以前に確認した。これでウェブサービスを使ったサイト構築がずいぶんと簡単になった。しかし今日問題にぶち当たった。
「AmazonウェブサービスにRESTでリクエストを投げ、受け取ったXMLをsimpleXMLに放り込んで、XpathでXMLツリー構造内を検索して配列にする」ということをやりたかった。実際そのように記述してみたけど結果はNG。最後の配列が空になってしまう。なぜ。
$xmlObj =simplexml_load_string($xml);
$items=$xmlObj->xpath(‘//Item’);
var_dump($items);
楽天ではこんな感じで取得できた。楽天のときは、タグ名に「:(コロン)」があってうまく処理できずとまどったが、Xpathを使って切り抜けることができた(というかXMLをたどらなくていいのでこちらのほうが簡単)。今回も例にならってXpathをつかったけど、うまくいかなかった。理由はどうもnamespace(タグ内にxmlnsとかってかいてあるアレ)のようだ。楽天のときはnamespaceがなかったので問題が出なかっただけ。で、書き直した。
$xmlObj=simplexml_load_string($xml);
$nsArray=$xmlObj->getNamespaces();
$ns=array_shift($nsArray);
$xmlObj->registerXPathNamespace(‘amazonns’,$ns);
$items=$xmlObj->xpath(‘//amazonns:Item’);
var_dump($items);
Xpathを使用する際、namespaceが定義されている場合は、「namespaceはこれですよ」と登録しないといけないようだ(登録するときに適当に名前「amazonns」をつける)。Xpathで検索をかけるときは、その名前を使い、名前の配下のタグを検索させるような構造になるようだ。
とりあえず、これで結果を取得することはできた。しかし、やっぱりXMLの奥は深そうだ。