2010-05-06 90 views
10

如何更改php DOMElement的innerHTML?更改php DOMElement的innerHTML

+0

你不能,直接。你必須有一箇中間函數來接收一個字符串並把它變成一個DOMElement數組。你可以自己寫,儘管我確信網絡上存在類似的東西。 – 2010-05-06 03:06:25

+0

在php DOMElement類中沒有innerHTML屬性。嘗試尋找這裏:http://php.net/manual/en/class.domelement.php和在這裏:http://www.php.net/manual/en/class.domtext.php – Babiker 2010-05-06 03:39:21

回答

0

看一看這個庫PHP簡單的HTML DOM解析器http://simplehtmldom.sourceforge.net/

它看起來非常簡單。您可以更改您的元素的innertext屬性。它可能有幫助。

+1

PHP,而不是JavaScript .. PHP的DOM實現沒有'innerHTML'屬性。 – 2010-05-06 03:04:56

+1

是的,我的錯。但php5的HTML DOM解析器有'innertext'。 http://simplehtmldom.sourceforge.net/ – Jull 2010-05-06 03:11:07

+0

這不是OP所指的圖書館。見:http://php.net/manual/en/book.dom.php但你可以編輯你的答案,並鏈接到你找到的庫,看看OP是否要切換。 – 2010-05-06 03:54:18

1

我認爲你可以做的最好的事情是拿出一個函數,它將採用你想要更改InnerHTML的DOMElement,將其複製並替換它。

在非常粗糙的PHP:

function replaceElement($el, $newInnerHTML) { 
    $newElement = $myDomDocument->createElement($el->nodeName, $newInnerHTML); 
    $el->parentNode->insertBefore($newElement, $el); 
    $el->parentNode->removeChild($el); 

    return $newElement; 
} 

這並沒有考慮到的屬性和嵌套結構,但我認爲這將讓你對你的方式。

+2

對於其他人試用此代碼 - 我不得不使用$ el-> parentNode-> insertBefore而不是$ el-> insertBefore。 – whichdan 2012-01-03 06:48:45

+0

這適用於設置innerText而不是innerHTML。 createElement的第二個參數不接受HTML格式。 – Greg 2012-01-25 21:49:33

+0

同意,@greg。這將HTML編碼字符。 – Kafoso 2016-11-18 13:44:36

7

我需要最近的一個項目做到這一點,結束了一個延伸到一個DOMElement:http://www.keyvan.net/2010/07/javascript-like-innerhtml-access-in-php/

這裏是展示它是如何使用的例子:

<?php 
require_once 'JSLikeHTMLElement.php'; 
$doc = new DOMDocument(); 
$doc->registerNodeClass('DOMElement', 'JSLikeHTMLElement'); 
$doc->loadHTML('<div><p>Para 1</p><p>Para 2</p></div>'); 
$elem = $doc->getElementsByTagName('div')->item(0); 

// print innerHTML 
echo $elem->innerHTML; // prints '<p>Para 1</p><p>Para 2</p>' 

// set innerHTML 
$elem->innerHTML = '<a href="http://fivefilters.org">FF</a>'; 

// print document (with our changes) 
echo $doc->saveXML(); 
?> 
0

這裏是一個由類函數我更換剛纔寫道:

它會替換class的innerHtml。您還可以指定節點類型,例如。 DIV/P/A等

function replaceInnerHtmlByClass($html, $replace=null, $class=null, $nodeType=null){ 
    if(!$nodeType){ $nodeType = '*'; } 
    $dom = new DOMDocument(); 
    $dom->loadHTML($html); 
    $xpath = new DOMXPath($dom); 
    $nodes = $xpath->query("//{$nodeType}[contains(concat(' ', normalize-space(@class), ' '), '$class')]"); 
    foreach($nodes as $node) { 
    while($node->childNodes->length){ 
     $node->removeChild($node->firstChild); 
    } 
    $fragment = $dom->createDocumentFragment(); 
    $fragment->appendXML($replace); 
    $node->appendChild($fragment); 
    } 
    return $dom->saveHTML($dom->documentElement); 
} 

這裏是另一個函數我寫信給刪除節點與特定的類,但保留了內部HTML。

將replace設置爲true會丟棄內部html。

設置替換爲任何其他內容將取代內部的HTML與提供的內容。

function stripTagsByClass($html, $class=null, $nodeType=null, $replace=false){ 
    if(!$nodeType){ $nodeType = '*'; } 
    $dom = new DOMDocument(); 
    $dom->loadHTML($html); 
    $xpath = new DOMXPath($dom); 
    $nodes = $xpath->query("//{$nodeType}[contains(concat(' ', normalize-space(@class), ' '), '$class')]"); 
    foreach($nodes as $node) { 
    $innerHTML = ''; 
    $children = $node->childNodes; 
    foreach($children as $child) { 
     $tmp = new DOMDocument(); 
     $tmp->appendChild($tmp->importNode($child,true));  
     $innerHTML .= $tmp->saveHTML(); 
    } 
    $fragment = $dom->createDocumentFragment(); 
    if($replace !== null && $replace !== false){ 
     if($replace === true){ $replace = ''; } 
     $innerHTML = $replace; 
    } 
    $fragment->appendXML($innerHTML); 
    $node->parentNode->replaceChild($fragment, $node); 
    } 
    return $dom->saveHTML($dom->documentElement); 
} 

這些函數可以很容易地適用於使用其他屬性作爲選擇器。

我只需要它來評估類的屬性。

1

似乎appendXML並不總是工作 - 例如,如果您嘗試追加3級的XML。下面是我寫的總是工作(您想設置$內容innerHTML來$元素)的功能:

function setInnerHTML($DOM, $element, $content) { 
    $DOMInnerHTML = new DOMDocument(); 
    $DOMInnerHTML->loadHTML($content); 
    $contentNode = $DOMInnerHTML->getElementsByTagName('body')->item(0)->firstChild; 
    $contentNode = $DOM->importNode($contentNode, true); 
    $element->appendChild($contentNode); 
    return $elementNode; 
} 
+1

返回的變量'$ elementNode'未定義 - 不應該是'$ contentNode'嗎? 您可以使用'$ element-> ownerDocument'來簡化函數,而不必傳入'$ DOM'。 這隻會導入任何$ content包含的第一個孩子。要導入整個片段,請刪除第4行的' - > firstChild'。 – 2016-01-01 11:25:50

-1

這裏是你如何做到這一點:

$doc = new DOMDocument(''); 
$label = $doc->createElement('label'); 

$label->appendChild($doc->createTextNode('test')); 
$li->appendChild($label); 

echo $doc->saveHTML(); 
0

從喬安娜九策的回答發展上時,該功能將插入一個文本節點或HTML片段:

function nodeFromContent($node, $content) { 
    //creates a text node, or dom node if content contains html 
    $lt = strpos($content, '<'); 
    $gt = strrpos($content, '>'); 
    if (!($lt === false || $gt === false) && $gt > $lt) { 
     //< followed by > means potentially contains HTML 
     $DOMInnerHTML = new DOMDocument(); 
     $DOMInnerHTML->loadHTML($content); 
     $contentNode = $DOMInnerHTML->getElementsByTagName('body')->item(0); 
     $newNode = $node->ownerDocument->importNode($contentNode, true); 
    } else { 
     $newNode = $node->ownerDocument->createTextNode($content); 
    } 
    return $newNode; 
} 

用法

$newNode = nodeFromContent($node, $content); 
$node->parentNode->insertBefore($newNode, $node); 
//or $node->appendChild($newNode) depending on what you require 
0
function setInnerHTML($DOM, $element, $innerHTML) { 
    $node = $DOM->createTextNode($innerHTML); 
    $element->appendChild($node); 
} 
2

另一種解決方案:

1)創建新DOMDocumentFragment從HTML要插入的字符串; 2)刪除我們元素的舊內容,刪除它的子節點; 3)將DOMDocumentFragment附加到我們的元素。

function setInnerHTML($element, $html) 
{ 
    $fragment = $element->ownerDocument->createDocumentFragment(); 
    $fragment->appendXML($html); 
    while ($element->hasChildNodes()) 
     $element->removeChild($element->firstChild); 
    $element->appendChild($fragment); 
} 

或者,我們可以用它代替clean copy我們的元素,然後追加DOMDocumentFragment這個克隆。

function setInnerHTML($element, $html) 
{ 
    $fragment = $element->ownerDocument->createDocumentFragment(); 
    $fragment->appendXML($html); 
    $clone = $element->cloneNode(); // Get element copy without children 
    $clone->appendChild($fragment); 
    $element->parentNode->replaceChild($clone, $element); 
} 

測試:

$doc = new DOMDocument(); 
$doc->loadXML('<div><span style="color: green">Old HTML</span></div>'); 
$div = $doc->getElementsByTagName('div')->item(0); 
echo $doc->saveHTML(); 

setInnerHTML($div, '<p style="color: red">New HTML</p>'); 
echo $doc->saveHTML(); 

// Output: 
// <div><span style="color: green">Old HTML</span></div> 
// <div><p style="color: red">New HTML</p></div> 
+0

雖然此代碼段可能會解決問題,[包括解釋](// meta。stackexchange.com/questions/114762/explaining-entirely-code-based-answers)確實有助於提高您的帖子的質量。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。也請儘量不要用解釋性註釋來擠佔代碼,這會降低代碼和解釋的可讀性! – 2016-08-07 15:11:06

1

我最終使使用的一些功能從其他人在此頁上該功能。我從更改了一個,喬安娜Goch的方式,彼得品牌大多說,並且還添加了一些代碼來賓和從其他地方。

該函數不使用擴展名,也不使用appendXML(即使它看到一個未關閉的BR標籤,它也是非常挑剔和破壞的)並且看起來運行良好。

function set_inner_html($element, $content) { 
    $DOM_inner_HTML = new DOMDocument(); 
    $internal_errors = libxml_use_internal_errors(true); 
    $DOM_inner_HTML->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8')); 
    libxml_use_internal_errors($internal_errors); 
    $content_node = $DOM_inner_HTML->getElementsByTagName('body')->item(0); 
    $content_node = $element->ownerDocument->importNode($content_node, true); 
    while ($element->hasChildNodes()) { 
     $element->removeChild($element->firstChild); 
    } 
    $element->appendChild($content_node); 
}