<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="http://blog.xole.net/rss/style.css" type="text/css"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:content="http://purl.org/rss/1.0/modules/content/"
         xmlns:dc="http://purl.org/dc/elements/1.1/"
         xml:lang="ja">
<channel rdf:about="http://blog.xole.net/rss/1.0.php?id=577">
<title>ハタさんのブログ(復刻版)</title>
<link>http://blog.xole.net/index.php</link>
<dc:date>2007-06-26T02:21:37+09:00</dc:date>
<description>
ハタさんのブログ(復刻版) - RSS (RDF Site Summary).
</description>
<items>
<rdf:Seq>
<rdf:li rdf:resource="http://blog.xole.net/article.php?id=577" />
</rdf:Seq>
</items>
</channel>
<item>
<title>Javascripterへ捧げるPHPのDOM</title>
<link>http://blog.xole.net/article.php?id=577</link>
<dc:date>2007-06-26T02:21:37+09:00</dc:date>
<description>HTMLテンプレートの話題を書こうと思ったけど、その話題に入る前にPHPのDOMについて書きます。

PHPのDOM(DOM関数)はいわゆるDOM APIを操作することのできるモジュールです。
このDOMのインタフェースはDOM Le...</description>
<content:encoded>
<![CDATA[
<p>HTMLテンプレートの話題を書こうと思ったけど、その話題に入る前にPHPのDOMについて書きます。</p>

<p>PHPのDOM(<a href="http://jp.php.net/manual/ja/ref.dom.php">DOM関数</a>)はいわゆるDOM APIを操作することのできるモジュールです。<br />
このDOMのインタフェースはDOM Level3をサポートしているので、javascriptでDOM操作をやったことのある人なら日常何度も目にすることがあるメソッドだらけです。</p>

<p>(中略)</p>

<p>以下に簡単なHTMLを用意し、同様の操作をPHPとjsの2つで表現します。<br />
やっている内容はid属性のNodeについて、文字列の置き換えやノードの追加/置換などです。</p>

<pre>
<code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
                      &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
        &lt;title&gt;ほげったらほげ&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div id=&quot;head&quot;&gt;headだよーん&lt;/div&gt;
        &lt;div id=&quot;contents&quot;&gt;
            &lt;input type=&quot;button&quot; id=&quot;btn&quot; value=&quot;buttonだよーん&quot; /&gt;
        &lt;/div&gt;
        &lt;div id=&quot;foot&quot;&gt;
            &lt;p id=&quot;footMessage&quot;&gt;footだよーん&lt;/p&gt;
        &lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code>
</pre>

<h3>まずはJavascript</h3>

<pre class="javascript">
<span class="keyword" >var</span> head = document.getElementById(<span class="string" >'head'</span>);
alert(head.nodeName); <span class="comment" >// div</span>
alert(head.tagName); <span class="comment" >// div</span>
alert(head.nodeType); <span class="comment" >// 1</span>
head.textContent = <span class="string" >'headだったの'</span>;

<span class="keyword" >var</span> contents = document.getElementById(<span class="string" >'contents'</span>);
<span class="keyword" >var</span> textarea = document.createElement(<span class="string" >'textarea'</span>);
    textarea.setAttribute(<span class="string" >'col'</span>, 20);
    textarea.setAttribute(<span class="string" >'row'</span>, 30);
    textarea.setAttribute(<span class="string" >'id'</span>, <span class="string" >'textId'</span>);
contents.appendChild(textarea);

<span class="keyword" >var</span> input = document.getElementById(<span class="string" >'btn'</span>);
    input.setAttribute(<span class="string" >'value'</span>, <span class="string" >'hello world'</span>);
    input.setAttribute(<span class="string" >'onclock'</span>, <span class="string" >'hoge(this)'</span>);

<span class="keyword" >var</span> foot = document.getElementById(<span class="string" >'foot'</span>);
<span class="keyword" >var</span> p = document.createElement(<span class="string" >'p'</span>);
    p.textContent = <span class="string" >'My Message'</span>;
foot.replaceChild(p, document.getElementById(<span class="string" >'footMessage'</span>));

<span class="keyword" >var</span> textareas = document.getElementsByTagName(<span class="string" >'textarea'</span>);
<span class="keyword" >for</span>(<span class="keyword" >var</span> i = 0; i &lt; textareas.length; i++){
    <span class="keyword" >var</span> textarea = textareas.item(i);
        textarea.value = <span class="string" >'qwerty'</span>;
    alert(textarea.getAttribute(<span class="string" >'id'</span>));
}

alert(document.body.innerHTML);
</pre>

<p>なんてことはない、ただのDOM操作です。<br />
textContentとかは動かないのがあるかもわからない。</p>

<h3>次にPHP</h3>

<pre class="php">
<span class="vars" >$document</span> = <span class="keyword" >new</span> DOMDocument(<span class="string" >'1.0'</span>, <span class="string" >'UTF-8'</span>);
<span class="vars" >$document</span>-&gt;load(dirname(<span class="keyword" >__FILE__</span>) . <span class="string" >'/index.html'</span>);
<span class="keyword" >if</span>(!<span class="vars" >$document</span>-&gt;validate()){
    <span class="keyword" >throw</span> <span class="keyword" >new</span> Exception(<span class="string" >'invalid file'</span>);
}

<span class="vars" >$head</span> = <span class="vars" >$document</span>-&gt;getElementById(<span class="string" >'head'</span>);
<span class="func" >echo</span> <span class="vars" >$head</span>-&gt;nodeName, PHP_EOL; <span class="comment" >// div</span>
<span class="func" >echo</span> <span class="vars" >$head</span>-&gt;tagName, PHP_EOL; <span class="comment" >// div</span>
<span class="func" >echo</span> <span class="vars" >$head</span>-&gt;nodeType, PHP_EOL; <span class="comment" >// 1</span>
<span class="vars" >$head</span>-&gt;nodeValue = <span class="string" >'headだったの'</span>;

<span class="vars" >$contents</span> = <span class="vars" >$document</span>-&gt;getElementById(<span class="string" >'contents'</span>);
<span class="vars" >$textarea</span> = <span class="vars" >$document</span>-&gt;createElement(<span class="string" >'textarea'</span>);
<span class="vars" >$textarea</span>-&gt;setAttribute(<span class="string" >'col'</span>, 20);
<span class="vars" >$textarea</span>-&gt;setAttribute(<span class="string" >'row'</span>, 30);
<span class="vars" >$textarea</span>-&gt;setAttribute(<span class="string" >'id'</span>, <span class="string" >'textId'</span>);
<span class="vars" >$contents</span>-&gt;appendChild(<span class="vars" >$textarea</span>);

<span class="vars" >$input</span> = <span class="vars" >$document</span>-&gt;getElementById(<span class="string" >'btn'</span>);
<span class="vars" >$input</span>-&gt;setAttribute(<span class="string" >'value'</span>, <span class="string" >'hello world'</span>);
<span class="vars" >$input</span>-&gt;setAttribute(<span class="string" >'onclock'</span>, <span class="string" >'hoge(this)'</span>);

<span class="vars" >$foot</span> = <span class="vars" >$document</span>-&gt;getElementById(<span class="string" >'foot'</span>);
<span class="vars" >$p</span> = <span class="vars" >$document</span>-&gt;createElement(<span class="string" >'p'</span>);
<span class="vars" >$p</span>-&gt;nodeValue = <span class="string" >'My Message'</span>;
<span class="vars" >$foot</span>-&gt;replaceChild(<span class="vars" >$p</span>, <span class="vars" >$document</span>-&gt;getElementById(<span class="string" >'footMessage'</span>));

<span class="vars" >$textareas</span> = <span class="vars" >$document</span>-&gt;getElementsByTagName(<span class="string" >'textarea'</span>);
<span class="comment" >//foreach($textareas as $textarea){</span>
<span class="keyword" >for</span>(<span class="vars" >$i</span> = 0; <span class="vars" >$i</span> &lt; <span class="vars" >$textareas</span>-&gt;length; <span class="vars" >$i</span>++){
    <span class="vars" >$textarea</span> = <span class="vars" >$textareas</span>-&gt;item(<span class="vars" >$i</span>);
    <span class="vars" >$textarea</span>-&gt;nodeValue = <span class="string" >'qwerty'</span>;
    <span class="func" >echo</span> <span class="vars" >$textarea</span>-&gt;getAttribute(<span class="string" >'id'</span>), PHP_EOL;
}

var_dump(<span class="vars" >$document</span>-&gt;saveXML());
</pre>

<p>javascriptで操作したときと同じですよね（たぶん)</p>

<h3>出力結果</h3>

<p>この2つの出力結果はどちらも同じで、次のようにでます。</p>

<pre>
<code>div
div
1
textId
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
    &lt;head&gt;
        &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
        &lt;title&gt;ほげったらほげ&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div id=&quot;head&quot;&gt;headだったの&lt;/div&gt;
        &lt;div id=&quot;contents&quot;&gt;
            &lt;input type=&quot;button&quot; id=&quot;btn&quot; value=&quot;hello world&quot; onclock=&quot;hoge(this)&quot; /&gt;
        &lt;textarea col=&quot;20&quot; row=&quot;30&quot; id=&quot;textId&quot;&gt;qwerty&lt;/textarea&gt;&lt;/div&gt;
        &lt;div id=&quot;foot&quot;&gt;
            &lt;p&gt;My Message&lt;/p&gt;
        &lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code>
</pre>

<p>PHPでもjsでも似たコードでDOMを扱えるってのは、便利です。（それだけ)</p>

<h3>(後略)</h3>

<p>HTMLテンプレートを作るならDOMモジュールが一番便利で、とっつきやすいです。<br />
また、デザイナーさんとかが作った綺麗なXHTMLをSmartyとかでぶっ壊すこと無くDOM操作できるのは非常に良い点であるといえます。<br />
できるだけカスタマイズ性を残しつつ、フレームワーク的な要素を採り入れると強力なテンプレートエンジンができるんじゃないかなーと思いつつ色々触っている今日このごろ。</p>
]]>
</content:encoded>
</item>

</rdf:RDF>