PHPでXMLをnamespaceを利用したxpathでnode取得
PHPでxmlを読み込んでxpathでnodeを取得して見たいと思います。
今回はyahooの形態素解析apiから取得したxmlを題材にしてみます。
XMLオブジェクトの操作
順を追ってxmlを操作してみます。
ちなみにyahooの形態素解析は前回のcurlを利用して取得できます。
$data = array( 'appid' => self::APP_ID, 'results' => 'ma', 'sentence' => trim($name) ); $response = $this->getGetRequestResponse($data);
いろいろと端折っていますが、とりあえずこれでxmlの文字列が取得できます。
SimpleXMLObjectの生成
先ほど取得した、xml文字列からPHPにあるSimpleXMLObjectを生成してみます。
$xml = simplexml_load_string($xmlString);
これは文字列を引数にxmlのオブジェクトを生成しているわけですね。
これでオブジェクトができました。
namespaceを設定する
yahooのapiを利用して取得したxmlにはnamespaceが設定されていますので、そのままxpathを解析させてもちゃんとデータが取得できません。
そのため、ここで設定してみます。
$xml->registerXPathNamespace('y', 'urn:yahoo:jp:jlp');
第一引数は、そのnamespaceに対するエイリアスみたいなものでしょうか。この名前を利用してxpathを実行します。
第二引数では、xml内で宣言されている名前の付いていないxmlnsを指定しています。
これでnamespaceを利用しつつちゃんとxpathでデータが取得できるようになります。
C#であればnamespaceなどを全部無視してxpathを実行したりできるのですがphpにもあるのでしょうか?
xpathの実行
ではxpathを指定しつつ、取得したデータを利用してみます。
$words = $xml->xpath('//y:ResultSet/y:ma_result/y:word_list/y:word'); $data = array(); foreach($words as $word){ array_push($data, (string)$word->surface, (string)$word->reading); } return $data;
xpathを実行する際に、先ほど設定したnamespaceを指定しつつ実行します。
そしてここでは複数取得されてくるためforeachで回して、中身を配列に突っ込んでいます。
$word->surfaceなどのままでと、以下のようなものも文字列ではなくSimpleXMLObjectで取れてくるため、stringでキャストする事でnode内の文字として取得しています。
<word> <surface>佐藤</surface> <reading>さとう</reading> </word>