PHP で XML を扱う

久々の技術記事を書く時間をようやく捻出。
が、残念ながら .NET(C#)/XNA ではなくて、タイトル通り PHP/XML である。
実際にいじっているのだから仕方がない。
 
ということで、PHPXML を扱う技術について今回は書いてみようと思う。
まず、使うのは SimpleXML.
 
DOM や DOM/XML(やや古) というのもあるし、そちらの方が詳細に XML を扱うことが出来るが些かコーディングが面倒である。
わかりにくいし。
いや、XML の基礎知識が足りてないのかもしれないが、その追求は今回割愛する。都合良く。
 
SimpleXML の良さはなんと言ってもその名の通り、シンプルさ。
概念がとても簡単で理解しやすい。
 
 
 
例として、次のような XML を扱うとしよう。
 

<?xml version="1.0" encoding="UTF-8"?>
<database>
  <redcarpet>
    <items>
      <item>
        <name>世界のナベアツ</name>
        <gag>オモロー</gag>
      </item>
    </items>
  </redcarpet>
</database>

 
これまで大きな勘違いをしておりまして。
SimpleXML は XML Read 用のライブラリだと思っていたんですね。
 
上記のデータファイル名が「data.xml」だとすると。
 

$xml = simplexml_load_file('data.xml');
echo $xml->redcarpet->items->item->name;
echo ' のギャグは ';
echo $xml->redcarpet->items->item->gag;
// 世界のナベアツ のギャグは オモロー

 
とか書いて「オモロー」と表示させるだけのものだと思っていました。
事前調査が劇的に不足していました。
 

simplexml_import_dom -- DOM ノードから SimpleXMLElement オブジェクトを取得する
simplexml_load_file -- XMLファイルをパースし、オブジェクトに代入する
simplexml_load_string -- XML 文字列をオブジェクトに代入する

 
基本、XML ファイルからデータを読むから、simple_import_dom 使わないと SimpleXMLElement のメソッドは使えないと思っていたのが大きな間違い。
simplexml_load_file/simple_load_string も戻り値は SimpleXMLElement 型だった。
 
今まで PHP + XML で自サイトを構築した中で、XML 更新部分は DOM を交えてひーこらやっていたのは単なるオマヌケだったと最近気づいた。
 

SimpleXMLElement->addAttribute() -- SimpleXML 要素に属性を追加する
SimpleXMLElement->addChild() -- XML ノードに子要素を追加する
SimpleXMLElement->asXML() -- SimpleXML 要素に基づき整形式の XML 文字列を返す
SimpleXMLElement->attributes() -- 要素の属性を定義する
SimpleXMLElement->children() -- 指定したノードの子ノードを見付ける
SimpleXMLElement->__construct() -- 新しい SimpleXMLElement オブジェクトを作成する
SimpleXMLElement->getDocNamespaces() -- ドキュメントで宣言されている名前空間を返す
SimpleXMLElement->getName() -- XML 要素の名前を取得する
SimpleXMLElement->getNamespaces() -- ドキュメントで使用している名前空間を返す
SimpleXMLElement->registerXPathNamespace() -- 次の XPath クエリ用の prefix/ns コンテキストを作成する
SimpleXMLElement->xpath() -- XML データに Xpath クエリを実行する

 
こんなに使えるメソッドがいやがった。。。
先ほどの例で使った XML にデータを追加したいとします。

      <item>
        <name>ザ・パンチ</name>
        <gag>砂漠でラクダに逃げられてぇー!</gag>
      </item>

 

$xml = simplexml_load_file('data.xml');
$item = $xml->redcarpet->items->addChild( 'item' ); // XMLノードに子要素追加
$item->addChild( 'name', 'ザ・パンチ' ); // XMLノードに子要素追加
$item->addChild( 'gag', '砂漠でラクダに逃げられてぇー!' ); // XMLノードに子要素追加
$xml->asXml('data.xml'); // 引数を指定することでファイルへの書き込みができる

 
と、こんな感じで割とお手軽に PHPXML を扱えてしまう。
もっと早くに気づいていれば良かった。。。
 
ちなみに SimpleXML は PHP 5 系では標準モジュール扱いなので、特別何もせず使える。
良いことづくめ。
ちょっとだけ不満なのは、最終的に出来上がる XML ファイルの中身の改行を意識出来ないこと。
 
最終的に出来る XML(data.xml)。

<?xml version="1.0" encoding="UTF-8"?>
<database>
  <redcarpet>
    <items>
      <item>
        <name>世界のナベアツ</name>
        <gag>オモロー</gag>
      </item>
      <item><name>ザ・パンチ</name><gag>砂漠でラクダに逃げられてぇー!</gag></item>
    </items>
  </redcarpet>
</database>

 
ホントはこうなって欲しい。

<?xml version="1.0" encoding="UTF-8"?>
<database>
  <redcarpet>
    <items>
      <item>
        <name>世界のナベアツ</name>
        <gag>オモロー</gag>
      </item>
      <item>
        <name>ザ・パンチ</name>
        <gag>砂漠でラクダに逃げられてぇー!</gag>
      </item>
    </items>
  </redcarpet>
</database>

 
ギャグの一覧を表示するページを創る。オマケ。

<html>
<head><title>ギャグ一覧</title></head>
<body>
<?php
$xml = simplexml_load_file('data.xml');
foreach( $xml->redcarpet->items->item as $itemid => $item ){
  echo $item->name . "" . $item->gag . "<br>\n";
}
/*
世界のナベアツ → オモロー<br>
ザ・パンチ → 砂漠でラクダに逃げられてぇー!<br>
*/
?>
</body>
</html>

 
 
 
※ここに記載したコードは動作試験をしていないので注意