  | 
      
        
          11樓
          巨大八爪鱼
          2016-1-15 19:01
          
          
           
         
        【更新】 以下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);     } }
  
       | 
    
    
        | 
      
        
          12樓
          巨大八爪鱼
          2016-1-15 20:50
          
          
           
         
        【更新】 以下版本的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);     } }
  
       | 
    
    
        | 
      
        
          13樓
          巨大八爪鱼
          2016-1-15 20:55
          
          
           
         
        【以下演示如何在加載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>
  
       | 
    
    
        | 
      
        
          14樓
          巨大八爪鱼
          2016-1-15 20:57
          
          
           
         
        【運行效果】   
       | 
    
    
        | 
      
        
          15樓
          巨大八爪鱼
          2016-1-15 20:59
          
          
           
         
         由於HTML模板文件中的文字仍是英文,所以在Dreamweaver的設計視圖中仍然能夠看到這些文字,方便編輯。 如果只用PHP的代碼塊(例如<?=_('Orange')?>),那麼在設計視圖中就只能看到PHP塊標記  ,十分影響網頁設計。  
       | 
    
    
        | 
      
        
          16樓
          巨大八爪鱼
          2016-1-15 21:01
          
          
           
         
        【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>
  
       | 
    
    
        | 
      
        
          17樓
          巨大八爪鱼
          2016-2-10 22:52
          
          
           
         
        【示例代碼】用面向對象的方法來實現上述內容: 【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);     } }
  
       | 
    
    
        | 
      
        
          18樓
          巨大八爪鱼
          2016-2-10 22:52
          
          
           
         
        【訪問頁:example.php】 <?php  libxml_use_internal_errors(true); include_once('HTMLPage.php'); include_once('ExamplePage.php'); $page = new ExamplePage(); $page->show();
  
       | 
    
    
        | 
      
        
          19樓
          巨大八爪鱼
          2016-2-10 22:53
          
          
           
         
        【封裝的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();     } }
 
  
       | 
    
    
        | 
      
        
          20樓
          巨大八爪鱼
          2016-2-10 22:53
          
          
           
         
        【最終輸出頁面】   
       |