|  | 【方案】用PHP自带的DOM类将HTML与PHP标签分离 | 
                
          |   一派护法 十九级 | 
              【最终HTML输出】 <!DOCTYPE html> <html><head><meta charset="utf-8"><title>My PHP Template Example</title><style> body {     font-family: Arial;     font-size: 12px; } mark {     background-color: #F9F9F9;     border: 1px solid #DDDDDD;     border-radius: 2px;     font-family: monospace, Courier;     padding: 1px 4px; } p {     line-height: 1.5em;     margin: 3px 0px; } footer {     background-color: #EEEEEE;     font-size: 13px;     margin-top: 20px;     padding: 10px 0px;     text-align: center; } footer span {     color: red; } ul {     margin: 2px 0px;     padding-left: 16px; } ul.Navigator {     background-color: #5F5F5F;     font-family: "Segoe UI", Arial, sans-serif;     letter-spacing: 1px;     list-style: none;     padding-left: 0px;     overflow: hidden; } ul.Navigator li {     float: left; } ul.Navigator a {     color: white;     display: inline-block;     font-size: 17px;     padding: 10px 15px 9px;     text-decoration: none; } ul.Navigator a:hover {     background-color: black; } ul.Navigator a.active {     background-color: #73AF21; } </style></head><body> <nav><ul class="Navigator"><li><a href="?language=HTML">HTML</a></li>     <li><a href="?language=CSS" class="active">CSS</a></li>     <li><a href="?language=JavaScript">JAVASCRIPT</a></li>   </ul></nav><article><h1>microtime</h1>   <p>microtime() returns <mark>the current Unix timestamp with microseconds</mark>. This function is only available on operating systems that support the gettimeofday() system call.</p>   <ul><li><a href="http://www.php.net/">www.php.net</a></li><li><a href="http://www.youtube.com/">www.youtube.com</a></li>   </ul></article><article><h1>Displaying the widget</h1>   <p>This page explains how to display and customize the reCAPTCHA widget on your webpage.</p>   <ul><li><a href="http://www.google.com/">www.google.com</a></li><li><a href="http://www.facebook.com/">www.facebook.com</a></li><li><a href="http://en.wikipedia.org/">en.wikipedia.org</a></li>   </ul></article><footer>Time Elapsed: <span>0.000s</span></footer></body></html> 【最终页面效果】   | 
                
          |   一派护法 十九级 | 
              【HTML模板文件:template_example.html,该模板文件不含任何PHP代码块】<!doctype html>
 <html>
 <head>
 <meta charset="utf-8">
 <title>Untitled Document</title>
 <style>
 body {
 font-family: Arial;
 font-size: 12px;
 }
 mark {
 background-color: #F9F9F9;
 border: 1px solid #DDDDDD;
 border-radius: 2px;
 font-family: monospace, Courier;
 padding: 1px 4px;
 }
 p {
 line-height: 1.5em;
 margin: 3px 0px;
 }
 
 footer {
 background-color: #EEEEEE;
 font-size: 13px;
 margin-top: 20px;
 padding: 10px 0px;
 text-align: center;
 }
 footer span {
 color: red;
 }
 
 ul {
 margin: 2px 0px;
 padding-left: 16px;
 }
 
 ul.Navigator {
 background-color: #5F5F5F;
 font-family: "Segoe UI", Arial, sans-serif;
 letter-spacing: 1px;
 list-style: none;
 padding-left: 0px;
 overflow: hidden;
 }
 
 ul.Navigator li {
 float: left;
 }
 
 ul.Navigator a {
 color: white;
 display: inline-block;
 font-size: 17px;
 padding: 10px 15px 9px;
 text-decoration: none;
 }
 ul.Navigator a:hover {
 background-color: black;
 }
 ul.Navigator a.active {
 background-color: #73AF21;
 }
 </style>
 </head>
 
 <body>
 <nav>
 <ul class="Navigator">
 <li><a class="active" href="?language=HTML">HTML</a></li>
 <li><a href="?language=CSS">CSS</a></li>
 <li><a href="?language=JavaScript">JAVASCRIPT</a></li>
 </ul>
 </nav>
 <article>
 <h1>Article Example</h1>
 <p>This HTML tutorial contains hundreds of HTML examples.<br>
 With our online <mark>HTML editor</mark>, you can edit the HTML, and click on a button to view the result.</p>
 <ul>
 <li><a href="example">Link Example</a></li>
 </ul>
 </article>
 <footer>Time Elapsed: <span></span></footer>
 </body>
 </html>
 
 | 
                
          |   一派护法 十九级 | 
              【index.php】<?php
 $start = microtime(); # 获取脚本开始执行的时间
 libxml_use_internal_errors(true); # 忽略不合法标签的提示
 $doc = new DOMDocument();
 $doc->loadHTMLFile('template_example.html'); # 加载模板文件
 
 $languages = array('HTML', 'CSS', 'JavaScript');
 $language = filter_input(INPUT_GET, 'language', FILTER_SANITIZE_STRING); # 获取URL变量:?language
 $id = array_search($language, $languages); # 确定当前选中的选项卡的编号
 if ($id === false) {
 $id = 0; # 默认选中第一个选项卡
 }
 
 $path = new DOMXPath($doc);
 $nodes = $path->query('/html/body/nav/ul/li/a');
 if ($id != 0) {
 $nodes->item(0)->removeAttribute('class'); # 去除第一个选项卡默认的选中状态
 $nodes->item($id)->setAttribute('class', 'active'); # 选中新的选项卡
 }
 
 $nodes = $path->query('/html/head/title');
 $nodes->item(0)->nodeValue = 'My PHP Template Example'; # 设置网页标题
 
 /* 定义两篇文章数组,这两篇文章可以从数据库中获取 */
 class Article {
 public $title;
 public $content;
 public $links;
 }
 $arr = array();
 $arr[0] = new Article();
 $arr[0]->title = 'microtime';
 $arr[0]->content = 'microtime() returns <mark>the current Unix timestamp with microseconds</mark>. This function is only available on operating systems that support the gettimeofday() system call. ';
 $arr[0]->links = array('www.php.net', 'www.youtube.com');
 $arr[1] = new Article();
 $arr[1]->title = 'Displaying the widget';
 $arr[1]->content = 'This page explains how to display and customize the reCAPTCHA widget on your webpage.';
 $arr[1]->links = array('www.google.com', 'www.facebook.com', 'en.wikipedia.org');
 
 function removeChildren($node) {
 while ($node->childNodes->length > 0) {
 $node->removeChild($node->firstChild);
 }
 }
 
 function setInnerHTML($node, $newValue) {
 removeChildren($node);
 $doc = $node->ownerDocument;
 $fragment = $doc->createDocumentFragment();
 $fragment->preserveWhiteSpace = false;
 if (!empty($newValue)) {
 $fragment->appendXML(trim($newValue));
 $importedNode = $doc->importNode($fragment, true);
 $node->appendChild($importedNode);
 }
 }
 
 function getInnerHTML(DOMNode $element) {
 $innerHTML = '';
 foreach ($element->childNodes as $child) {
 $innerHTML .= $element->ownerDocument->saveHTML($child);
 }
 return $innerHTML;
 }
 
 # <artile> 标签循环
 $articleTemplate = $path->query('/html/body/article')->item(0); # 取<article>模板标签
 foreach ($arr as $article) {
 $articleNode = $articleTemplate->parentNode->insertBefore($articleTemplate->cloneNode(true), $articleTemplate); # 根据模板标签新增节点,并插入到模板标签之前
 $path->query('.//h1', $articleNode)->item(0)->nodeValue = $article->title; # nodeValue不允许存在HTML标签
 setInnerHTML($path->query('.//p', $articleNode)->item(0), $article->content); # setInnerHTML允许存在HTML标签
 
 # <li> 标签循环
 $linkTemplate = $path->query('.//ul/li', $articleNode)->item(0); # 取<li>模板标签
 foreach ($article->links as $link) {
 $linkNode = $linkTemplate->parentNode->insertBefore($linkTemplate->cloneNode(true), $linkTemplate);
 $anchorNode = $path->query('.//a', $linkNode)->item(0);
 $anchorNode->setAttribute('href', "http://$link/"); # 设置链接URL
 $anchorNode->nodeValue = $link; # 设置链接文本
 }
 $linkTemplate->parentNode->removeChild($linkTemplate); # 删除模板标签<li>
 }
 $articleTemplate->parentNode->removeChild($articleTemplate); # 删除模板标签<article>
 
 # 在页面底部显示本页面的总执行时间
 $nodes = $path->query('/html/body/footer/span');
 $now = microtime();
 $nodes->item(0)->nodeValue = number_format($now - $start, 3) . 's';
 
 echo $doc->saveHTML(); # 输出整个页面
 ?>
 
 | 
                
          |   一派护法 十九级 | 
              制作HTML模板文件时,可用浏览器直接访问这个HTML文件。  为了让正式服务器上的HTML模板文件不能被恶意访问,可以创建一个目录专门存放HTML模板,然后在该目录下设置一个.htaccess文件,写上Deny from all(注意Apache 2.2和2.4使用的指令完全不同)。             | 
                
          |   一派护法 十九级 | 
              网站目录结构:/css 存放CSS样式
 /templates 存放HTML模板文件
 /xxx.php 实际PHP页面
 当使用Dreamweaver制作HTML模板文件时,为了在设计视图中能正确显示CSS样式,可以将<link>标签中的CSS href文件路径写成"../css/xxx.css"的格式。
 而在xxx.php中调用HTML模板文件的时候,自动把所有引用CSS的<link>标签中的文件路径全部改为“css/xxx.css”。(当然如果使用了URL重写规则的话,则再作其他判断)
 
 如果使用了gettext多语言库,可以在HTML模板文件上全写英文原文,这样可以在Dreamweaver设计视图中显示,方便制作网页。然后PHP在调用HTML模板的时候,自动将模板文件中的所有标签(也可以设置一个标签列表)的nodeValue全部执行一次_()函数,将其翻译成当前所设语言的mo文件中的内容。
 
 | 
                
          |   一派护法 十九级 | 
              在PHP自带的DOM类中,还有getElementById和getElementsByTagName方法,使用这两个方法可以简化模板标签的提取。在上面的例子中,<article>标签循环的基本思路是:先取出模板文件中的<article>标签,复制该标签后插入到该标签的前面,循环结束后删除模板标签。
 
 | 
                
          |   一派护法 十九级 | 
              【示例2】 下面这个示例演示了如何把一段用户输入的乱七八糟的HTML代码显示到模板HTML文档中。 <?php  libxml_use_internal_errors(true); $doc = new DOMDocument(); $doc->loadHTMLFile('template_example.html'); function removeChildren($node) {     while ($node->childNodes->length > 0) {         $node->removeChild($node->firstChild);     } } function setInnerHTML($node, $html) {     removeChildren($node);     if (empty($html)) {         return;     }         $doc = $node->ownerDocument;     $htmlclip = new DOMDocument();     $htmlclip->loadHTML($html);     $clipNode = $doc->importNode($htmlclip->getElementsByTagName('body')->item(0), true);     while ($item = $clipNode->firstChild) {         $node->appendChild($item);     } } $articleNode = $doc->getElementsByTagName('article')->item(0); $html = '<P ID=id10 class=strangeclass>A paragraph<BR>   </p><br> <NAV class=sxxx>A HTML5 LABEL</NAV><p>Another paragraph</p><label><BR><A id=a48'; setInnerHTML($articleNode, $html); echo $doc->saveHTML(); libxml_clear_errors(); 【最终输出】 article标签附近: <article><p id="id10" class="strangeclass">A paragraph<br></p><br><nav class="sxxx">A HTML5 LABEL</nav><p>Another paragraph</p><label><br><a id="a48"></a></label></article> 【显示效果】   | 
                
          |   一派护法 十九级 | 
              对于乱七八糟破烂不堪的HTML代码,如果使用3楼所示的setInnerHTML函数的话,运行就会出现错误。因此,示例2中的setInnerHTML函数更完善一些,也更符合DOM标准。另外,关于在3楼的代码中用到的DOMDocumentFragment::appendXML函数,PHP官方手册上提到过这样一句话:If you want to stick to the standards, you will have to create a temporary
   DOMDocument with a dummy root and then loop through the child nodes of the
   root of your XML data to append them.
 这说明DOMDocumentFragment::appendXML是不符合DOM标准的。
 | 
                
          |   一派护法 十九级 | 
              index.php中的代码仍然比较乱。但是如果把页面处理封装成一个类,并继承HTMLPage类,且把removeChildren、setInnerHTML、getInnerHTML这样的通用函数放置到HTMLPage类中的话,代码就要简洁很多。在页面处理类IndexPage类中,显示底部footer的PHP代码可以单独弄一个方法,循环显示文章列表再单独弄一个函数,把所有函数公用的变量都设置为类实例变量,访问控制属性设置为privare。这样的话,就会使得以后的阅读和维护工作更加方便。
 | 
                
          |   一派护法 十九级 | 
              在HTMLPage类中,可以加入一个方法,使得模板页面中所有的TextNode中的文字全部自动被gettext库翻译一次(也就是执行_()函数)。当然,也要允许子类重写这个方法。
 | 
                
          |   一派护法 十九级 | 
              【更新】以下setInnerHTML函数解决了当$html未被任何节点包围时会自动产生<p>节点扰乱页面布局的问题。
 function setInnerHTML($node, $html) {
 removeChildren($node);
 if (empty($html)) {
 return;
 }
 
 $doc = $node->ownerDocument;
 $htmlclip = new DOMDocument();
 $htmlclip->loadHTML("<div>$html</div>");
 $clipNode = $doc->importNode($htmlclip->getElementsByTagName('body')->item(0)->firstChild, true);
 while ($item = $clipNode->firstChild) {
 $node->appendChild($item);
 }
 }
 
 以下setInnerHTML函数不仅解决了上面的问题,还阻止了$htmlclip自动产生HTML4文档声明部分以及head, body等多余的内容。
 该函数必须在PHP版本>=5.4.0以上的服务器环境中使用。如果环境不满足的话,就用上面的函数。
 function setInnerHTML($node, $html) {
 removeChildren($node);
 if (empty($html)) {
 return;
 }
 
 $doc = $node->ownerDocument;
 $htmlclip = new DOMDocument();
 $htmlclip->loadHTML("<div>$html</div>", LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);
 $clipNode = $doc->importNode($htmlclip->firstChild, true);
 while ($item = $clipNode->firstChild) {
 $node->appendChild($item);
 }
 }
 
 | 
                
          |   一派护法 十九级 | 
              【更新】以下版本的setInnerHTML函数解决了中文乱码的问题。
 function setInnerHTML($node, $html) {
 removeChildren($node);
 if (empty($html)) {
 return;
 }
 
 $doc = $node->ownerDocument;
 $htmlclip = new DOMDocument();
 $htmlclip->loadHTML('<meta http-equiv="Content-Type" content="text/html;charset=utf-8"><div>' . $html . '</div>');
 $clipNode = $doc->importNode($htmlclip->documentElement->lastChild->firstChild, true);
 while ($item = $clipNode->firstChild) {
 $node->appendChild($item);
 }
 }
 
 | 
                
          |   一派护法 十九级 | 
              【以下演示如何在加载HTML模板文件时自动用gettext翻译其中的文本内容,以及之后如何用sprintf替换其中的变量】【translate_example.php】
 <?php
 libxml_use_internal_errors(true);
 
 # 模拟gettext的_()函数
 function ____($text) {
 switch ($text) {
 case 'Untitled Document':
 return '无标题文档';
 case 'Article Example':
 return '文章示例';
 case 'This HTML tutorial contains %d HTML examples.':
 return '这个HTML教程中包含了%d个HTML示例。';
 case 'There are %s options in total.':
 return '共有%s个选项。';
 case 'Apple':
 return '苹果';
 case 'Orange':
 return '橘子';
 case 'Link Example':
 return '示例链接';
 case "\r\nWith our online ":
 return "\r\n使用我们的在线";
 case 'HTML editor':
 return 'HTML编辑器';
 case ', you can edit the HTML, and click on a button to view the result.':
 return ',您可以编辑HTML代码,并且点击按钮后就能看到运行结果。';
 case 'Time Elapsed: ':
 return '消耗的时间:';
 default:
 return $text; # 不能翻译的文字
 }
 }
 
 function translate($doc) {
 $path = new DOMXPath($doc);
 $textNodes = $path->query('/descendant::*/text()');
 for ($i = 0; $i < $textNodes->length; $i++) {
 $value = $textNodes->item($i)->nodeValue;
 if (trim($value) == '') {
 continue;
 }
 $textNodes->item($i)->nodeValue = ____($value);
 }
 }
 
 function removeChildren($node) {
 while ($node->childNodes->length > 0) {
 $node->removeChild($node->firstChild);
 }
 }
 
 function setInnerHTML($node, $html) {
 removeChildren($node);
 if (empty($html)) {
 return;
 }
 
 $doc = $node->ownerDocument;
 $htmlclip = new DOMDocument();
 $htmlclip->loadHTML('<meta http-equiv="Content-Type" content="text/html;charset=utf-8"><div>' . $html . '</div>');
 $clipNode = $doc->importNode($htmlclip->documentElement->lastChild->firstChild, true);
 while ($item = $clipNode->firstChild) {
 $node->appendChild($item);
 }
 }
 
 $doc = new DOMDocument();
 $doc->loadHTMLFile('template_example.html');
 $doc->formatOutput = true;
 
 translate($doc); # 翻译HTML模板中的文字
 
 # 选中第二个单选框
 $path = new DOMXPath($doc);
 $radios = $path->query('/html/body/form/input');
 $radios->item(1)->setAttribute('checked', 'checked');
 
 # 显示选项数量
 $pNode = $doc->getElementById('CountExamples');
 $pNode->firstChild->nodeValue = sprintf($pNode->firstChild->nodeValue, $radios->length); # $pNode指向<p>,firstChild指向<p>中的文本节点
 # 最好不要直接设置<p>的nodeValue的值,这样可能会导致两个相邻的<p>节点被合并而破坏页面布局
 $pNode = $doc->getElementById('CountOptions');
 setInnerHTML($pNode, sprintf($pNode->firstChild->nodeValue, '<span style="color:red">' . $radios->length . '</span>'));
 
 echo html_entity_decode($doc->saveHTML(), ENT_QUOTES, 'utf-8');
 
 /*
 PHP DOM不能识别HTML5的<meta charset="utf-8">标签
 但是能够识别HTML4的<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
 所以在输出的时候要使用html_entity_decode函数防止源文件中的中文被转换成HTML Entity表示。
 */
 
 【HTML模板:template_example.html】
 <!doctype html>
 <html>
 <head>
 <meta charset="utf-8">
 <title>Untitled Document</title>
 <style>
 body {
 font-family: Arial;
 font-size: 12px;
 }
 mark {
 background-color: #F9F9F9;
 border: 1px solid #DDDDDD;
 border-radius: 2px;
 font-family: monospace, Courier;
 padding: 1px 4px;
 }
 p {
 line-height: 1.5em;
 margin: 3px 0px;
 }
 
 footer {
 background-color: #EEEEEE;
 font-size: 13px;
 margin-top: 20px;
 padding: 10px 0px;
 text-align: center;
 }
 footer span {
 color: red;
 }
 
 ul {
 margin: 2px 0px;
 padding-left: 16px;
 }
 
 ul.Navigator {
 background-color: #5F5F5F;
 font-family: "Segoe UI", Arial, sans-serif;
 letter-spacing: 1px;
 list-style: none;
 padding-left: 0px;
 overflow: hidden;
 }
 
 ul.Navigator li {
 float: left;
 }
 
 ul.Navigator a {
 color: white;
 display: inline-block;
 font-size: 17px;
 padding: 10px 15px 9px;
 text-decoration: none;
 }
 ul.Navigator a:hover {
 background-color: black;
 }
 ul.Navigator a.active {
 background-color: #73AF21;
 }
 
 form {
 padding: 5px 0px;
 }
 </style>
 </head>
 
 <body>
 <nav>
 <ul class="Navigator">
 <li><a class="active" href="?language=HTML">HTML</a></li>
 <li><a href="?language=CSS">CSS</a></li>
 <li><a href="?language=JavaScript">JAVASCRIPT</a></li>
 </ul>
 </nav>
 <article>
 <h1>Article Example</h1>
 <p id="CountExamples">This HTML tutorial contains %d HTML examples.<br>
 With our online <mark>HTML editor</mark>, you can edit the HTML, and click on a button to view the result.</p>
 <ul>
 <li><a href="example">Link Example</a></li>
 </ul>
 </article>
 <form id="form1" name="form1" method="post">
 <input type="radio" name="radio" id="radio" value="apple"><label for="radio">Apple</label><br>
 <input type="radio" name="radio" id="radio2" value="orange"><label for="radio2">Orange</label>
 </form>
 <p id="CountOptions">There are %s options in total.</p>
 <footer>Time Elapsed: <span></span></footer>
 </body>
 </html>
 
 | 
                
          |   一派护法 十九级 | 
              【运行效果】   | 
                
          |   一派护法 十九级 | 
               由于HTML模板文件中的文字仍是英文,所以在Dreamweaver的设计视图中仍然能够看到这些文字,方便编辑。 如果只用PHP的代码块(例如<?=_('Orange')?>),那么在设计视图中就只能看到PHP块标记  ,十分影响网页设计。             | 
                
          |   一派护法 十九级 | 
              【HTML输出内容】<!DOCTYPE html>
 <html>
 <head>
 <meta charset="utf-8">
 <title>无标题文档</title>
 <style>
 body {
 font-family: Arial;
 font-size: 12px;
 }
 mark {
 background-color: #F9F9F9;
 border: 1px solid #DDDDDD;
 border-radius: 2px;
 font-family: monospace, Courier;
 padding: 1px 4px;
 }
 p {
 line-height: 1.5em;
 margin: 3px 0px;
 }
 
 footer {
 background-color: #EEEEEE;
 font-size: 13px;
 margin-top: 20px;
 padding: 10px 0px;
 text-align: center;
 }
 footer span {
 color: red;
 }
 
 ul {
 margin: 2px 0px;
 padding-left: 16px;
 }
 
 ul.Navigator {
 background-color: #5F5F5F;
 font-family: "Segoe UI", Arial, sans-serif;
 letter-spacing: 1px;
 list-style: none;
 padding-left: 0px;
 overflow: hidden;
 }
 
 ul.Navigator li {
 float: left;
 }
 
 ul.Navigator a {
 color: white;
 display: inline-block;
 font-size: 17px;
 padding: 10px 15px 9px;
 text-decoration: none;
 }
 ul.Navigator a:hover {
 background-color: black;
 }
 ul.Navigator a.active {
 background-color: #73AF21;
 }
 
 form {
 padding: 5px 0px;
 }
 </style>
 </head>
 <body>
 <nav><ul class="Navigator">
 <li><a class="active" href="?language=HTML">HTML</a></li>
 <li><a href="?language=CSS">CSS</a></li>
 <li><a href="?language=JavaScript">JAVASCRIPT</a></li>
 </ul></nav><article><h1>文章示例</h1>
 <p id="CountExamples">这个HTML教程中包含了2个HTML示例。<br>
 使用我们的在线<mark>HTML编辑器</mark>,您可以编辑HTML代码,并且点击按钮后就能看到运行结果。</p>
 <ul>
 <li><a href="example">示例链接</a></li>
 </ul></article><form id="form1" name="form1" method="post">
 <input type="radio" name="radio" id="radio" value="apple"><label for="radio">苹果</label><br><input type="radio" name="radio" id="radio2" value="orange" checked><label for="radio2">橘子</label>
 </form>
 <p id="CountOptions">共有<span style="color:red">2</span>个选项。</p>
 <footer>消耗的时间:<span></span></footer>
 </body>
 </html>
 
 | 
                
          |   一派护法 十九级 | 
              【示例代码】用面向对象的方法来实现上述内容:【ExamplePage.php】
 <?php
 class ExamplePage extends HTMLPage {
 private $startTime;
 
 function __construct() {
 $this->startTime = microtime();
 parent::__construct('template_example.html');
 
 $this->title = 'My Test Page';
 $this->changeTabs();
 $this->showArticles();
 $this->showFooter();
 }
 
 private function changeTabs() {
 $this->setActiveTab('/nav/ul/li/a', 1); // 选中第二个选项卡
 $this->setText('/nav/ul/li[1]/a', 'HTML5');
 $this->setText('/nav/ul/li[2]/a', 'CSS3');
 $this->setInnerHTML('/nav/ul/li[3]/a', '<b style="color:red">Java</b>Script');
 }
 
 private function showArticles() {
 $t_article = $this->queryBody('/article');
 for ($i = 1; $i <= 4; $i++) {
 $article = $this->duplicate($t_article);
 $this->setChildText($article, 'h1', "Article $i");
 $this->setChildHTML($article, 'p', "This is a <mark>paragraph</mark> of Article $i...");
 
 $t_link = $this->queryIn('ul/li', $article);
 for ($j = 1; $j <= 5; $j++) {
 $link = $this->duplicate($t_link);
 $n = ($i - 1) * 5 + $j;
 $this->setChildText($link, 'a', "Link $j")->setAttribute('href', "page$n.php");
 //$this->setChildAttribute($link, 'a', 'href', 'anotherpage.php');
 }
 $this->delete($t_link);
 }
 $this->delete($t_article);
 }
 
 private function showFooter() {
 $str = number_format(microtime() - $this->startTime, 3) . 's';
 $this->setText('/footer/span', $str);
 }
 }
 
 | 
                
          |   一派护法 十九级 | 
              【访问页:example.php】<?php
 libxml_use_internal_errors(true);
 include_once('HTMLPage.php');
 include_once('ExamplePage.php');
 $page = new ExamplePage();
 $page->show();
 
 | 
                
          |   一派护法 十九级 | 
              【封装的HTMLPage基类:HTMLPage.php】<?php
 class HTMLPage extends DOMDocument {
 private $path;
 
 function __construct($template) {
 $this->loadHTMLFile($template);
 $this->path = new DOMXPath($this);
 }
 
 function __get($property) {
 if ($property == 'title') {
 return $this->queryHead('/title', 0)->nodeValue;
 }
 }
 
 function __set($property, $value) {
 if ($property == 'title') {
 $this->queryHead('/title', 0)->nodeValue = $value;
 }
 }
 
 public function delete($node) {
 if (is_string($node)) {
 $node = $this->queryBody($node, 0);
 } elseif ($node instanceof DOMNodeList) {
 $node = $node->item(0);
 }
 return $node->parentNode->removeChild($node);
 }
 
 public function duplicate($templateNode) {
 if ($templateNode instanceof DOMNodeList) {
 $templateNode = $templateNode->item(0);
 }
 return $templateNode->parentNode->insertBefore($templateNode->cloneNode(true), $templateNode);
 }
 
 public function getInnerHTML(DOMNode $element) {
 $innerHTML = '';
 foreach ($element->childNodes as $child) {
 $innerHTML .= $element->ownerDocument->saveHTML($child);
 }
 return $innerHTML;
 }
 
 public function query($path, $item = NULL) {
 if (is_null($item)) {
 return $this->path->query($path);
 } else {
 return $this->path->query($path)->item($item);
 }
 }
 
 public function queryBody($path, $item = NULL) {
 return $this->query("/html/body$path", $item);
 }
 
 public function queryHead($path, $item = NULL) {
 return $this->query("/html/head$path", $item);
 }
 
 public function queryIn($path, $node, $item = NULL) {
 if (is_string($node)) {
 $node = $this->queryBody($node);
 }
 if (is_null($item)) {
 return $this->path->query(".//$path", $node);
 } else {
 return $this->path->query(".//$path", $node)->item($item);
 }
 }
 
 public function removeChildren($node) {
 while ($node->childNodes->length > 0) {
 $node->removeChild($node->firstChild);
 }
 }
 
 public function setActiveTab($nodeList, $index) {
 if (is_string($nodeList)) {
 $nodeList = $this->queryBody($nodeList);
 }
 $nodeList->item(0)->removeAttribute('class');
 $nodeList->item($index)->setAttribute('class', 'active');
 }
 
 public function setChildAttribute($node, $path, $attribute, $value) {
 $node = $this->queryIn($path, $node, 0);
 $node->setAttribute($attribute, $value);
 return $node;
 }
 
 public function setChildText($node, $path, $text) {
 $node = $this->queryIn($path, $node, 0);
 $node->nodeValue = $text;
 return $node;
 }
 
 public function setChildHTML($node, $path, $html) {
 $node = $this->queryIn($path, $node, 0);
 $this->setInnerHTML($node, $html);
 return $node;
 }
 
 public function setInnerHTML($node, $html) {
 if (is_string($node)) {
 $node = $this->queryBody($node, 0);
 }
 $this->removeChildren($node);
 if (empty($html)) {
 return;
 }
 
 $doc = $node->ownerDocument;
 $htmlclip = new DOMDocument();
 $htmlclip->loadHTML('<meta http-equiv="Content-Type" content="text/html;charset=utf-8"><div>' . $html . '</div>');
 $clipNode = $doc->importNode($htmlclip->documentElement->lastChild->firstChild, true);
 while ($item = $clipNode->firstChild) {
 $node->appendChild($item);
 }
 }
 
 public function setText($node, $text) {
 if (is_string($node)) {
 $node = $this->queryBody($node, 0);
 }
 $node->nodeValue = $text;
 }
 
 public function show() {
 echo $this->saveHTML();
 }
 }
 
 
 | 
                
          |   一派护法 十九级 | 
              【最终输出页面】   |