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の場合

 194: /**
 195:  * RSS1.0 の内容を配列に格納する
 196:  * @param   string $url RSS1.0のURL
 197:  * @param   array  $arr RSSの内容を格納する配列
 198:  *          getRDF[channel][title]
 199:  *                         [link]
 200:  *                [items][番号][title]
 201:  *                             [link]
 202:  *                             [description]
 203:  *                             [date]
 204:  * @return 格納したitemの数/FALSE=格納に失敗
 205: */
 206: function getRDF($url, &$arr) {
 207:     //PHP4用; DOM XML利用
 208:     if (isphp5over() == FALSE) {
 209:         $dom = read_xml($url);      //DOM XML利用
 210:         if (($rdf = $dom->get_elements_by_tagname('RDF')) == NULL)  return FALSE;
 211:         //channel情報の取得
 212:         $channel = $rdf[0]->get_elements_by_tagname('channel');
 213:         $node    = $rdf[0]->get_elements_by_tagname('title');
 214:         $arr['channel']['title'] = htmlspecialchars($node[0]->get_content());
 215:         $node    = $rdf[0]->get_elements_by_tagname('link');
 216:         $arr['channel']['link'] = htmlspecialchars($node[0]->get_content());
 217:         $item    = $rdf[0]->get_elements_by_tagname('item');
 218:         //item情報の取得
 219:         $i = 0;
 220:         while (isset($item[$i])) {
 221:             $node = $item[$i]->get_elements_by_tagname('title');
 222:             $arr['item'][$i]['title']       = htmlspecialchars($node[0]->get_content());
 223:             $node = $item[$i]->get_elements_by_tagname('link');
 224:             $arr['item'][$i]['link']        = htmlspecialchars($node[0]->get_content());
 225:             $node = $item[$i]->get_elements_by_tagname('description');
 226:             $arr['item'][$i]['description'] = htmlspecialchars($node[0]->get_content());
 227:             $node = $item[$i]->get_elements_by_tagname('date');
 228:             $arr['item'][$i]['date']        = htmlspecialchars($node[0]->get_content());
 229:             $i++;
 230:         }
 231: 
 232:     //PHP5用; SimpleXML利用
 233:     } else {
 234:         $rdf = @simplexml_load_file($url);
 235:         if ($rdf == FALSE)  return FALSE;
 236:         if (! isset($rdf->item))    return FALSE;
 237:         //channel情報の取得
 238:         $arr['channel']['title'] = htmlspecialchars($rdf->channel->title);
 239:         $arr['channel']['link']  = htmlspecialchars($rdf->channel->link);
 240:         //item情報の取得
 241:         $i = 1;
 242:         while (isset($rdf->item[$i]->title)) {
 243:             $arr['item'][$i]['title']        = htmlspecialchars($rdf->item[$i]->title);
 244:             $arr['item'][$i]['link']         = htmlspecialchars($rdf->item[$i]->link);
 245:             $arr['item'][$i]['description']  = htmlspecialchars($rdf->item[$i]->description);
 246:             $node = $rdf->item[$i]->children(NS_dc);
 247:             $arr['item'][$i]['date']         = htmlspecialchars($node->date);
 248:             $i++;
 249:         }
 250:         $i--;
 251:     }
 252:     return $i;
 253: }

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 メソッドを使う必要がある。

  37: //名前空間
  38: define('NS_dc',    'http://purl.org/dc/elements/1.1/');
  39: define('NS_rdf',   'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
  40: define('NS_xmlns', 'http://purl.org/rss/1.0/');
  41: 

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

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

参考サイト

(この項おわり)
header