名前空間がある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"; }
これで「はてなブックマーク」が取得できました。