2012-05-22 50 views
2

我有一個跟進問題,我的問題已經回答了@Jack: Wrap segments of HTML with divs (and generate table of contents from HTML-tags) with PHP裹在PHP H3標籤集合與DOM文檔之間的所有HTML標籤

我一直在嘗試一些功能添加到上面的答案,以獲得以下結果。

這是我現在的HTML:

<h3>Subtitle</h3> 
<p>This is a paragraph</p> 
<p>This is another paragraph</p> 
<h3>Another subtile<h3> 
<p>Yet another paragraph</p> 

這是我想什麼來實現:

<h3 class="current">Subtitle</h3> 
<div class="ac_pane" style="display:block;"> 
    <p>This is a paragraph</p> 
    <p>This is another paragraph</p> 
</div> 
<h3>Another subtitle</h3> 
<div class="ac_pane"> 
    <p>Yet another paragraph</p> 
</div> 

我一直在試圖修改代碼上面的例子,但可以不知道:

foreach ($d->getElementsByTagName('h3') as $h3) { 
    $ac_pane_nodes = array($h3); 
    for ($next = $h3->nextSibling; $next && $next->nodeName != 'h3'; $next = $next->nextSibling) { 
     $ac_pane_nodes[] = $next; 
    } 
    $ac_pane = $d->createElement('div'); 
    $ac_pane->setAttribute('class', 'ac_pane'); 
    // Here I'm trying to wrap all tags between h3-sets, but am failing! 
      $h3->parentNode->appendChild($ac_pane, $h3); 
    foreach ($ac_pane_nodes as $node) { 
     $ac_pane->appendChild($node); 
    } 
} 

請注意,class="current"的第一個h3設置,並增加style="display:block;"到第一個div.ac_pane是可選的,但將非常感謝!

任何人都可以請快速幫忙嗎?提前致謝。

+0

XSLT是我推薦的,但是與它分組是很複雜的,至少說(即將連續的p標籤分組到一個div中)是複雜的。這是需要考慮的事情。如果您願意接受XSLT解決方案,請告訴我。 – matb33

+0

謝謝!你檢查了上面的鏈接嗎?這個解決方案做了一些適當的分組,我只需要對它進行修改,以便它包含除了所討論的h3之外的所有內容......你可以看看嗎?提前致謝。 – maartenmachiels

+0

這個版本和鏈接之間有一個關鍵的區別。在鏈接版本中,h2被包含作爲獲取包裝的節點集的一部分,而在此版本中,h3不在集合中。這就是你遇到問題的地方。如果這個提示不能削減它,讓我知道,我會爲你寫一個工作版本 – matb33

回答

4

按照要求,這是一個工作版本。 IMO XSLT仍然是最適合這類問題的解決方案(實際上將一些XML轉換爲其他XML),但我不得不承認用常規代碼進行分組要容易得多!

我最終擴展了DOM API,只是爲了在DOMElement上添加實用工具insertAfter。它本來可以做,沒有它,但它的整潔:

更新到WRAP DIV周圍的所有標籤的要求,在評論

<?php 

class DOMDocumentExtended extends DOMDocument { 
    public function __construct($version = "1.0", $encoding = "UTF-8") { 
     parent::__construct($version, $encoding); 
     $this->registerNodeClass("DOMElement", "DOMElementExtended"); 
    } 
} 

class DOMElementExtended extends DOMElement { 
    public function insertAfter($targetNode) { 
     if ($targetNode->nextSibling) { 
      $targetNode->parentNode->insertBefore($this, $targetNode->nextSibling); 
     } else { 
      $targetNode->parentNode->appendChild($this); 
     } 
    } 

    public function wrapAround(DOMNodeList $nodeList) { 
     while (($node = $nodeList->item(0)) !== NULL) { 
      $this->appendChild($node); 
     } 
    } 
} 

$doc = new DOMDocumentExtended(); 
$doc->loadHTML(
    "<h3>Subtitle</h3> 
    <p>This is a paragraph</p> 
    <p>This is another paragraph</p> 
    <h3>Another subtile</h3> 
    <p>Yet another paragraph</p>" 
); 

// Grab a nodelist of all h3 tags 
$nodeList = $doc->getElementsByTagName("h3"); 

// Iterate over each of these h3 nodes 
foreach ($nodeList as $index => $h3) { 

    // Special handling for first h3 
    if ($index === 0) { 
     $h3->setAttribute("class", "current"); 
    } 

    // Create a div node that we'll use as our wrapper 
    $div = $doc->createElement("div"); 
    $div->setAttribute("class", "ac_pane"); 

    // Special handling for first div wrapper 
    if ($index === 0) { 
     $div->setAttribute("style", "display:block;"); 
    } 

    // Move next siblings of h3 until we hit another h3 
    while ($h3->nextSibling && $h3->nextSibling->localName !== "h3") { 
     $div->appendChild($h3->nextSibling); 
    } 

    // Add the div node right after the h3 
    $div->insertAfter($h3); 
} 

// UPDATE: wrap all child nodes of body in a div 
$div = $doc->createElement("div"); 
$body = $doc->getElementsByTagName("body")->item(0); 
$div->wrapAround($body->childNodes); 
$body->appendChild($div); 

echo $doc->saveHTML(); 

注意loadHTML將新增DOCTYPE,html和身體節點。 They can be stripped out if needed

+0

非常感謝!我會盡快測試並嘗試實施您的代碼,並會盡快獲得批准。 – maartenmachiels

+0

謝謝,這個解決方案完美的工作!非常感謝! – maartenmachiels

+0

只是最後一個小細節:有沒有一種快速簡單的方法來包裝這個新創建的HTML與另一個div? – maartenmachiels