こうやって使うのか!!
(ノ・・)ン。。。。。。(((●コロコロッ
サンプルとしてこういったものを用意した。
email.xml
このXMLは
PEAR::Mail_mimeを使ってHTMLメールを分解し、
Mail_mimeDecode::getXML()で出力したものだ。
さて、プログラマ諸君。
このXMLからテキストメールのbody部分を取得するプログラムを考えてみてくれたまへ。(何様!?
[More:]
ぶっちゃけ言います。
「XMLって何が便利なんだろう・・・?」
と思ってました。
以前XSLTの便利さに気がついたのでそれを記事にした。
しかし、そんなのはXMLの便利さの氷山の一角に過ぎなかったのだ。
では、XMLの最大の利点はなにか。
それは
XPATHクエリー
今ページを見ている人の中で、
普段データベースを使う人は多いと思う。
データベースはSQLクエリーを発行し結果を取得するという仕組みだが、
XMLでも同等の事が出来ると聞いたらどう思うだろうか?
配列では上から下まで参照しなければデータは取れない。
オブジェクトの配列でも同様。
ハッシュではクエリーに該当するのはキーだけ。
しかし、XMLではピンポイントでデータを取得したり、
式に該当するものだけ取得したりすると言うことが可能なのだ。
さて、冒頭に戻ろう。
ご自身ではどんな解答が出てきただろうか?
私はPHPプログラマなのでPHPで答えることにする。
手元にあるのがPHP5なのでそれで。
<?php
$doc = new DOMDocument("1.0", "UTF-8");
$doc->load( "email.xml" );
$xpath = new DOMXPath( $doc );
$query = '/email/descendant::mimepart/body[(../header/headervalue/text() = "text/plain")]';
$body = $xpath->query( $query )->item(0)->nodeValue;
echo $body;
?>
Σ( ̄ロ ̄; コレダケ!?
多少の違いはあるだろうし、
サンプルだからセキュリティうんぬんはとりあえず省いている。
が、たったこれだけで二つ以上ネストしているデータを取り出すのは他の方法は思いつかない。
しかも、メールは仕組み上送信側のクライアントに依存する部分が大きい。
この方法ならどんなパターンのマルチパートメールでも、
テキストメールのbody部分が取れる。
なので、シングルパートとマルチパートの分岐だけ作れば、
メールの本文データ取得はこれで終わってしまうのだ。
配列でも同様にn次元を固定にすれば一発で取れる。
しかし、送信側が好き勝手に作って送ってくるメールの内容を、
添え字固定で取得するのは問題有りではないだろうか?
なので配列を使用する場合は上から下まで確認することになるだろう。
解説するとしよう。
用意した
サンプルXMLファイル。
メールを分解したものなのだが、
マルチパートのメールなので階層構造がややこしくなっている。
肝になるのは以下のコード部分。
この文字列をXPATHという。
$query = '/email/descendant::mimepart/body[(../header/headervalue/text() = "text/plain")]';
その他はXpathを利用するための準備だと思ってもらえばいい。
queryという変数名でピンと来る人もいると思うが、
これはデータベースを取り扱っているのと同じ感覚だ。
クエリの内容は
- /email子孫のmimepartを探す
- mimepart以下のbodyを探す
- mimepart以下のheader以下のheadervalueの値を検索
- 文字列"text/plain"で検索
- 結果はbodyを返す
と言った具合だ。
Xpathと聞くと「xmlをpath指定したもの」という印象を持つが、
SQLのXML版と思ってもらった方が良い。
詳しくは
Xpath仕様を読んで欲しい。
さすがにXPATHを自前でこつこつやるのは骨が折れる。
そこはそれ。
XPathを生成してくれるツールなんてのもある。
XPath式エディタ2
・ハマリポイント。
XPATH式エディタで生成したクエリだが、
DOMXPathで分解できない場合がある。
その際warningが発生する。
マルチバイトは基本UTF-8以外は受け付けない。
あらかじめ変換しておくこと。
仕組み上、オーバーヘッドは多め。
使う場所は間違えないように。