Upload
hiraku-nakano
View
2.030
Download
0
Embed Size (px)
Citation preview
{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>
文字列連結
< “ > & → < " > &
エスケープを確実に
壊れた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で書けるよ!
<?phprequire_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;
すっきりしますね!