如何更改php DOMElement的innerHTML?
答案 0 :(得分:8)
我最近需要为一个项目执行此操作,最后得到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();
?>
答案 1 :(得分:4)
另一种解决方案:
1)从要插入的HTML字符串中创建新的DOMDocumentFragment; 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>
答案 2 :(得分: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;
}
这不会考虑属性和嵌套结构,但我认为这会让你顺利进行。
答案 3 :(得分:1)
似乎appendXML始终不起作用 - 例如,如果您尝试追加3级XML。这是我写的总是有效的函数(你想将$ content作为innerHTML设置为$ element):
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;
}
答案 4 :(得分:1)
我最终使用此页面上其他人的一些功能来创建此功能。我以 Peter Brand 的方式改变了 Joanna Goch 中的那个,并且还添加了来自 Guest 和其他地方的一些代码。
此函数不使用扩展名,并且不使用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 );
}
答案 5 :(得分:0)
看看这个库PHP Simple HTML DOM Parser http://simplehtmldom.sourceforge.net/
看起来很简单。您可以更改元素的innertext
属性。这可能有所帮助。
答案 6 :(得分:0)
这是我刚刚写的类函数替换:
它将替换类的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);
}
可以轻松调整这些函数以使用其他属性作为选择器。
我只需要它来评估类属性。
答案 7 :(得分:0)
根据Joanna Goch的回答,该函数将插入文本节点或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
答案 8 :(得分:0)
function setInnerHTML($DOM, $element, $innerHTML) {
$node = $DOM->createTextNode($innerHTML);
$element->appendChild($node);
}
答案 9 :(得分:-1)
这是你如何做到的:
$doc = new DOMDocument('');
$label = $doc->createElement('label');
$label->appendChild($doc->createTextNode('test'));
$li->appendChild($label);
echo $doc->saveHTML();