Markup

Builder (出力制御)

Author : trashtoy

Table of Contents

概要

Builder はノードを文字列に変換する処理を担当する抽象基底クラスです. 具象クラスとして DefaultBuilderDebugBuilder の 2 種類が用意されています.

エンドユーザーが新しい Builder クラスを定義することも出来ますが, よほど特殊な用途でもない限り DefaultBuilder のみで充分でしょう. 独自の Builder を新たに作成する方法については Builder を自作する方法 を参照してください.

DefaultBuilder

DefaultBuilder は Builder クラスの標準的な実装です. DefaultBuilder には以下の 3 種類のオブジェクトがセットされています.

  • Renderer: タグの出力方法を制御します.
  • Indent: インデントと改行コードの文字列をカスタマイズすることが出来ます. インデントレベルの初期値を変更することも出来ます.
  • BreakControl: コードを改行する場所を制御します.

以下, DefaultBuilder の使い方のサンプルです.

Renderer

Renderer はタグの出力を制御するインタフェースです. 主に空要素タグや Boolean 属性の出力方法に関係します.

実装クラスとして SgmlRendererXmlRenderer の 2 種類があります. デフォルトでは XmlRenderer がセットされています. エンドユーザーが Renderer オブジェクトを直接使う機会はないため, 通常使用する分には特にこれらのクラスを意識する必要はないでしょう. 以下のように setRenderer() の引数に文字列または Renderer オブジェクトを指定することで Renderer を切り替えることが出来ます.

  1. $builder new Peach_Markup_DefaultBuilder();
  2.  
  3. // 以下の 2 つの書き方は等価です
  4. $builder->setRenderer("SGML");
  5. $builder->setRenderer(Peach_Markup_SgmlRenderer::getInstance());
  6.  
  7. // 以下の 2 つの書き方は等価です
  8. $builder->setRenderer("XML");
  9. $builder->setRenderer(Peach_Markup_XmlRenderer::getInstance());

setRenderer() の引数に文字列を指定する場合, 有効な値は "XML", "XHTML", "SGML", "HTML" のいずれかとなります. 大文字・小文字は問いません.

Renderer を切り替えることにより, 以下のように出力が変化します. input 要素の checked 属性や br 要素の出力の違いに注目してください. (変数 $node を構築するコードは割愛します)

  1. $builder new Peach_Markup_DefaultBuilder();
  2. $builder->setRenderer("XML");
  3. echo $builder->build($node);
  4. /*
  5. Output:
  6. <form method="post" action="sample.php">
  7.     Name
  8.     <input type="text" name="param1" value="" />
  9.     <br />
  10.     <input type="checkbox" name="flag1" value="1" checked="checked" />
  11.     Enable something
  12.     <br />
  13.     <input type="submit" name="submit" value="Send" />
  14. </form>
  15.  */
  16.  
  17. $builder->setRenderer("SGML");
  18. echo $builder->build($node);
  19. /*
  20. Output:
  21. <form method="post" action="sample.php">
  22.     Name
  23.     <input type="text" name="param1" value="">
  24.     <br>
  25.     <input type="checkbox" name="flag1" value="1" checked>
  26.     Enable something
  27.     <br>
  28.     <input type="submit" name="submit" value="Send">
  29. </form>
  30.  */

Indent

Indent は出力されるコードのインデントの文字列や改行コードの種類をカスタマイズするクラスです. 以下の要領で使用します.

  1. インデントレベル (初期値は 0 です), インデント文字列, 改行コード を指定して新しい Indent オブジェクトを生成します.
  2. 生成した Indent オブジェクトを setIndent() の引数に指定して DefaultBuilder にセットします.
  3. DefaultBuilder の build() を実行します.

以下にサンプルコードを掲載します.

  1. $builder new Peach_Markup_DefaultBuilder();
  2. $space   Peach_Markup_Indent::TAB;
  3. $br      Peach_Markup_Indent::LF;
  4. $builder->setIndent(new Peach_Markup_Indent(0$space$br));
  5. echo $builder->build($node);

Indent オブジェクトをセットしない場合, デフォルトの設定で以下の条件でインデントが行われます.

  • インデントレベル: 0
  • インデント文字列: 半角スペース 4 個
  • 改行コード: CRLF

BreakControl

BreakControl はコードを改行する箇所を制御するクラスです. デフォルトでは手書きの HTML や XML のような自然な改行とインデントを自動で行いますが, 特定のタグだけ例外的に改行しない, といった細かなカスタマイズをすることが出来ます.

例として Peach_Markup_NameBreakControl クラスを使って特定のタグのみ強制改行をするサンプルコードを掲載します. NameBreakControl のコンストラクタ引数に指定された tag2, tag4 要素が強制的に改行されます.

  1. $tag1 new Peach_Markup_ContainerElement("tag1");
  2. $tag2 new Peach_Markup_ContainerElement("tag2");
  3. $tag3 new Peach_Markup_ContainerElement("tag3");
  4. $tag4 new Peach_Markup_ContainerElement("tag4");
  5.  
  6. $tag1->append("This is sample 1");
  7. $tag2->append("This is sample 2");
  8. $tag3->append("This is sample 3");
  9. $tag4->append("This is sample 4");
  10.  
  11. $root new Peach_Markup_ContainerElement("root");
  12. $root->append($tag1);
  13. $root->append($tag2);
  14. $root->append($tag3);
  15. $root->append($tag4);
  16.  
  17. $builder new Peach_Markup_DefaultBuilder();
  18. $builder->setBreakControl(new Peach_Markup_NameBreakControl(array("tag2""tag4")array()));
  19. echo $builder->build($root);
  20.  
  21. /*
  22. Output:
  23. <root>
  24.     <tag1>This is sample 1</tag1>
  25.     <tag2>
  26.         This is sample 2
  27.     </tag2>
  28.     <tag3>This is sample 3</tag3>
  29.     <tag4>
  30.         This is sample 4
  31.     </tag4>
  32. </root>
  33.  */

インデントをなくして出力データをできるだけ削減したい場合は Peach_Markup_MinimalBreakControl を使用してください. さきほどのノードを MinimalBreakControl を使って build した場合のサンプルコードを掲載します.

  1. $builder new Peach_Markup_DefaultBuilder();
  2. $builder->setBreakControl(Peach_Markup_MinimalBreakControl::getInstance());
  3. echo $builder->build($root);
  4. /*
  5. Output:
  6. <root><tag1>This is sample 1</tag1><tag2>This is sample 2</tag2><tag3>This is sample 3</tag3><tag4>This is sample 4</tag4></root>
  7.  */

DebugBuilder

DebugBuilder はノードのツリー構造を可視化するための Builder です. 名前の通りデバッグ用途に使用します.

例えば HTML (XML) コードの断片を Code オブジェクトとしてノードの中に組み込む場合に役に立つでしょう. 以下にサンプルコードを掲載します. DefaultBuilder で build した場合に 2 つの p 要素が同じように出力されますが, DebugBuilder で build した場合は 1 番目の p 要素が Code オブジェクトで 2 番目の p 要素が ContainerElement であることが分かります.

  1. $code new Peach_Markup_Code("<p>This is a Code object.</p>");
  2. $p    new Peach_Markup_ContainerElement("p");
  3. $p->append("This is a Text object.");
  4.  
  5. $div new Peach_Markup_ContainerElement("div");
  6. $div->append($code);
  7. $div->append($p);
  8.  
  9. echo $b1->build($div);
  10. /*
  11. Output:
  12. <div>
  13.     <p>This is a Code object.</p>
  14.     <p>This is a Text object.</p>
  15. </div>
  16.  */
  17.  
  18. $b2->build($div);
  19. /*
  20. Output:
  21. ContainerElement(div) {
  22.     Code
  23.     ContainerElement(p) {
  24.         Text
  25.     }
  26. }
  27.  */