darudaru

だるだるしてるエンジニア

名前空間があるXMLをPHPでパースする

Gmailでフィルタリングしている対象のメールのsubjectを取得したくて、フィルタのXMLをパースするプログラムを作ったけれども、空でしかデータが取得できず四苦八苦しました。

取得したいデータはXMLの名前空間を使って定義されていたのですが、PHPで名前空間で指定されているXMLのデータを取得するためにはちょっと処理を追加する必要があるらしい。それに気づくまで結構時間がかかってしまった。

名前空間で定義されているXML

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:apps='http://schemas.google.com/apps/2006'>
<entry>
<category term='filter'></category>
<title>Mail Filter</title>
<id>tag:mail.google.com,2008:filter:1481761382935</id>
<updated>2017-02-20T01:52:15Z</updated>
<content></content>
<apps:property name='from' value='xxx@xxx'/>
<apps:property name='subject' value='はてなブックマーク'/>
<apps:property name='label' value='はてな'/>
<apps:property name='sizeOperator' value='s_sl'/>
<apps:property name='sizeUnit' value='s_smb'/>
</entry>
<entry></entry>

<apps:property name='subject' value='はてなブックマーク'/>が名前空間で指定している部分。そして今回取得したいデータです。
このXMLをsimplexml_load_file()でパースするだけだと、名前空間で指定されているapps:propertyのデータは空のオブジェクトとなってしまいます。

名前空間で指定されているXMLをパースする

<?php
$xml_obj = simplexml_load_file('mailFilters.xml');
// 名前空間を取得する
$nameSpaces = $xml_obj->getNamespaces(true);
foreach($xml_obj->entry as $entry){
  // <entry>下の名前空間appsの1番目の要素の属性の値をstring型に変換して出力する
  echo $entry->children($nameSpaces['apps'])->property[1]->attributes()->value->__toString() . "¥n";
}

これで「はてなブックマーク」が取得できました。