{
XML_Builderの紹介
@Hiraku
 @Hiraku (中野 拓)
 某ポータルサイトのPHPプログラマ
 PHP歴4年
 好きなフレームワーク
 Zend Framework
 YAF
自己紹介
http://blog.tojiru.net/
https://github.com/hirak
今日はXMLの話です
• XML概要・問題点整理
• XML_Builderのご提案
• おまけ
 RSS, Atom
 WebAPI
 GData
 OData
 KML
 Gadget.xml
 何とか.xmlたくさん
XMLと言えば
まだまだ現役
PHPでXMLを扱うなら…
<XML/>
読む 書く
• SimpleXML
• DOM
• XMLReader
• その他いろいろ
↑こっちの話をします
1. 文字列連結
2. DOM
3. XMLWriter
XMLを書く
<?php $data = range(0,3) ?>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<?php foreach ($data as $v): ?>
<child><?php echo $v?></child>
<?php endforeach ?>
</root>
文字列連結
< “ > & → &lt; &quot; &gt; &amp;
 エスケープを確実に
 壊れたXMLになってしまうかも
 タグの対応
 インデントを保つのがつらい
文字列連結の問題
→おすすめしない
1. 文字列連結
2. DOM
3. XMLWriter
じゃあDOMはどうだ
 メモリ上にXMLのツリー構造を作り、最後に
出力する
 出力するまでは書き換え可能
 HTMLでの出力
 →高機能
 メモリを消費する & 重い
 http://php.net/manual/ja/book.dom.php
DOM
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://example.com/">
<child>foo</child>
</root>
<?php
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->formatOutput = true;
$root = $doc->createElement('root');
$root->setAttribute('xmlns', 'http://example.com/');
$child = $doc->createElement('child');
$text = $doc->createTextNode('foo');
$child->appendChild($text);
$root->appendChild($child);
$doc->appendChild($root);
echo $doc->saveXML();
DOMのコード
長い。
読みにくい。
1. 文字列連結
2. DOM
3. XMLWriter
じゃあXMLWriterはどうだ
 ストリームに即座に書き出していく
 後ろに戻れない →DOMより低機能
 速くて軽い
 http://php.net/manual/ja/book.xmlwriter.php
XMLWriter
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://example.com/">
<child>foo</child>
</root>
XMLWriterのコード
<?php
$w = new XMLWriter;
$w->openURI('php://output');
$w->setIndent(true);
$w->setIndentString(' ');
$w->startDocument('1.0','UTF-8');
$w->startElement('root');
$w->writeAttribute('xmlns',
'http://example.com/');
$w->startElement('child');
$w->text('foo');
$w->endElement();
$w->endELement();
$w->endDocument();
長い。
読みにくい。
もっと美しく書けない
ものか。
{ラッパー作ったよ
XML_Builderの紹介
 PHP5.2対応PEARライブラリ
 とにかく短くXMLを書ける言語内DSL
 自動エスケープ
 差し替え可能なバックエンド
 まったく同じコードでDOM, XMLWriterが使い
分けられる
 arrayも作れる = JSONやYAMLも吐き出せる
 http://openpear.org/package/XML_Builder
XML_Builderとは
 pear channel-discover openpear.org
 pear install openpear/XML_Builder
インストールは超簡単
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://example.com/">
<child>foo</child>
</root>
XML_Builderのコード
<?php
require_once 'XML/Builder.php';
XML_Builder::factory()
->root(array('xmlns'=>'http://example.com/'))
->child_('foo')
->_
->_echo;
適当な解説
<?php
require_once 'XML/Builder.php';
XML_Builder::factory()
->root(array('xmlns'=>'http://example.com/'))
->child_('foo')
->_
->_echo;
←インスタンスを生成
↑任意のメソッドは要素の追加になる
連想配列を渡すと属性になる
↑メソッドが_で終わると要素が即閉じる
←できあがったXMLを即出力
↑直近の要素を閉じる
 classでバックエンドの切り替え
 dom, xmlwriter, array
 formatOutput
 encoding, version
$json_builder = XML_Builder::factory(array(
'class' => 'array',
'serializer' => 'json_encode',
));
factory()のオプション
JSONで出力
<?php
require_once 'XML/Builder.php';
XML_Builder::factory(array(
'class'=>'array',
'serializer'=>'json_encode',
))
->root(array('xmlns'=>'http://example.com/'))
->child_('foo')
->_
->_echo;
{"root":{"@xmlns":"http://example.com/","child":"foo"}}
{もちろん書けます
動的なXML
$hoge = 'Foo'
/* ... */
->$hoge($hoge)
/* ... */
->{$hoge . '_'}($hoge)
変数
←要素名もテキストも変数が
使える
←要素名に複雑な文字列を使う
条件分岐、繰り返し(1)
->_do(function($b) use($a){
if ($a) {
$b->a();
}
foreach (range(0,3) as $v) {
$b->b($v);
}
})
_doメソッドと無名関数で何でも
埋め込める
条件分岐、繰り返し(2)
->xmlPause($b); //ビルダーを$bに保存してチェーンを分
断
foreach (range(0,3) as $v) {
$b->li($v);
}
$b //チェーンを再開
-> ...
PHP5.2用
 似たような文法のライブラリは他にもあるんで
すが、バックエンド差し替えはオリジナルです
 詳しい文法はドキュメントで
 http://hirak.github.com/xmlbuilder/
 このドキュメントもXML_Builderで書いてます
その他
 WebAPIを作るとき
 XML, JSON, JSONP, PHPSerialize 出力対応!
とかやりたい場合
 HTML用テンプレートエンジンとしては微妙…
おすすめ用途
 DOMやXMLWriterは安全だが
素で書くと面倒くさい
 ラッパーライブラリを使えば簡単に書ける
 XML_Builder使ってみてください!!
まとめ
おまけ
http://d.hatena.ne.jp/sotarok/20080725/php_study_34_simplexml_code
それXML_Builderで
書けるよ!
<?php
require_once 'XML/Builder.php';
XML_Builder::factory(array('doctype' => XML_Builder::$HTML4_TRANSITIONAL))
->html(array('lang' => 'ja'))
->head
->meta_(array(
'http-equiv' => 'Content-Type',
'content' => 'text/html; charset=UTF-8'
))
->meta_(array(
'http-equiv' => 'Content-Style-Type',
'content' => 'text/css'
))
->meta_(array(
'http-equiv' => 'Content-Script-Type',
'content' => 'text/javascript'
))
->meta_(array('name' => 'robots', 'content' => 'INDEX,FOLLOW'))
->title_('DOMで HTML かいたりしませんか')
->_
->body_
->_
->_echo;
すっきりしますね!

Xml builderの紹介