PHPでコロンを含むXML要素名を扱う方法

(1/1)
いままで XML を扱う際に、PHP 4.x では DOM XML を、PHP 5.x では SimpleXML を利用してきた。
これらは便利な関数群だが、XML要素名にコロン「」を含む場合、そのままでは扱うことができない。たとえば RSS 1.0 では、"dc:date" のように、コロンを含む要素名があり、処理に工夫が必要だ。

XML の要素名にコロン「」を含む場合、名前空間(name space)が関係してくる。
今回は、RSS 1.0 を題材に、Simple XML で名前空間を扱う方法を紹介する。

(2021 年 10 月 10 日)PHP8 対応,リファラ・チェック改良など

目次

サンプル・プログラムの実行例

PHPでコロンを含むXML要素名を扱う方法

サンプル・プログラム「RSS 1.0 ビューア」

圧縮ファイルの内容
RSS10view.phpサンプル・プログラム本体

解説:DOM XMLの場合

0194: /**
0195:  * RSS1.0 の内容を配列に格納する
0196:  * @param   string $url RSS1.0のURL
0197:  * @param   array  $arr RSSの内容を格納する配列
0198:  *          getRDF[channel][title]
0199:  *                         [link]
0200:  *                [items][番号][title]
0201:  *                             [link]
0202:  *                             [description]
0203:  *                             [date]
0204:  * @return 格納したitemの数/FALSE=格納に失敗
0205: */
0206: function getRDF($url, &$arr) {
0207:     //PHP4用; DOM XML利用
0208:     if (isphp5over() == FALSE) {
0209:         $dom = read_xml($url);       //DOM XML利用
0210:         if (($rdf = $dom->get_elements_by_tagname('RDF')) == NULL)  return FALSE;
0211:         //channel情報の取得
0212:         $channel = $rdf[0]->get_elements_by_tagname('channel');
0213:         $node    = $rdf[0]->get_elements_by_tagname('title');
0214:         $arr['channel']['title'] = htmlspecialchars($node[0]->get_content());
0215:         $node    = $rdf[0]->get_elements_by_tagname('link');
0216:         $arr['channel']['link'] = htmlspecialchars($node[0]->get_content());
0217:         $item    = $rdf[0]->get_elements_by_tagname('item');
0218:         //item情報の取得
0219:         $i = 0;
0220:         while (isset($item[$i])) {
0221:             $node = $item[$i]->get_elements_by_tagname('title');
0222:             $arr['item'][$i]['title']       = htmlspecialchars($node[0]->get_content());
0223:             $node = $item[$i]->get_elements_by_tagname('link');
0224:             $arr['item'][$i]['link']        = htmlspecialchars($node[0]->get_content());
0225:             $node = $item[$i]->get_elements_by_tagname('description');
0226:             $arr['item'][$i]['description'] = htmlspecialchars($node[0]->get_content());
0227:             $node = $item[$i]->get_elements_by_tagname('date');
0228:             $arr['item'][$i]['date']        = htmlspecialchars($node[0]->get_content());
0229:             $i++;
0230:         }
0231: 
0232:     //PHP5用; SimpleXML利用
0233:     } else {
0234:         $rdf = @simplexml_load_file($url);
0235:         if ($rdf == FALSE)  return FALSE;
0236:         if (! isset($rdf->item))  return FALSE;
0237:         //channel情報の取得
0238:         $arr['channel']['title'] = htmlspecialchars($rdf->channel->title);
0239:         $arr['channel']['link']  = htmlspecialchars($rdf->channel->link);
0240:         //item情報の取得
0241:         $i = 1;
0242:         while (isset($rdf->item[$i]->title)) {
0243:             $arr['item'][$i]['title']        = htmlspecialchars($rdf->item[$i]->title);
0244:             $arr['item'][$i]['link']         = htmlspecialchars($rdf->item[$i]->link);
0245:             $arr['item'][$i]['description']  = htmlspecialchars($rdf->item[$i]->description);
0246:             $node = $rdf->item[$i]->children(NS_dc);
0247:             $arr['item'][$i]['date']         = htmlspecialchars($node->date);
0248:             $i++;
0249:         }
0250:         $i--;
0251:     }
0252:     return $i;
0253: }

RSS 1.0 の内容を配列変数に格納するユーザー関数が getRDF である。
内部では、PHP 4.x の場合と PHP 5.x の場合とで処理を分岐させている。

関数 get_elements_by_tagname では、要素名にコロンを含む場合、コロンの右側を認識する。そこで、get_elements_by_tagname('date') としてやれば、要素 "dc:date" の値を取得することができる。

なお、配列変数 $arr に代入する際にいちいち関数  htmlspecialchars  を適用しているのは、クロスサイトスクリプティング対策のためである。

解説:SimpleXMLの場合

Simple XML の場合、"$rdf->item[$i]->dc:date" では要素の内容を取得することができない。名前空間を指定し、children メソッドを使う必要がある。

0037: //名前空間
0038: define('NS_dc',    'http://purl.org/dc/elements/1.1/');
0039: define('NS_rdf',   'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
0040: define('NS_xmlns', 'http://purl.org/rss/1.0/');
0041: 

RSS 1.0 で使う名前空間は、あらかじめ定数で定義しておく。

children メソッドで子ノード $node を取得したら、"$node->dc" と指定することで、要素 "dc:date" の内容を取り出すことができる。

参考サイト

(この項おわり)
header