如何将 HTML 插入到 PHP DOMNode?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4400980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to insert HTML to PHP DOMNode?
提问by Nazariy
Is there any way I can insert an HTML template to existing DOMNode without content being encoded?
有什么方法可以在不编码内容的情况下将 HTML 模板插入现有的 DOMNode 吗?
I have tried to do that with:
我试图做到这一点:
$dom->createElement('div', '<h1>Hello world</h1>');
$dom->createTextNode('<h1>Hello world</h1>');
The output is pretty much the same, with only difference that first code would wrap it in a div. I have tried to loadHTML from string but I have no idea how can I append it's body content to another DOMDocument.
输出几乎相同,唯一的区别是第一个代码将它包装在一个 div 中。我试图从字符串加载HTML,但我不知道如何将它的正文内容附加到另一个 DOMDocument。
In javascript, this process seems to be quite simple and obvious.
在 javascript 中,这个过程似乎非常简单和明显。
采纳答案by Gumbo
It works with another DOMDocument for parsing the HTML code. But you need to import the nodesinto the main document before you can use them in it:
它与另一个 DOMDocument 一起用于解析 HTML 代码。但是您需要先将节点导入到主文档中,然后才能在其中使用它们:
$newDiv = $dom->createElement('div');
$tmpDoc = new DOMDocument();
$tmpDoc->loadHTML($str);
foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
$node = $dom->importNode($node, true);
$newDiv->appendChild($node);
}
And as a handy function:
作为一个方便的功能:
function appendHTML(DOMNode $parent, $source) {
$tmpDoc = new DOMDocument();
$tmpDoc->loadHTML($source);
foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
$node = $parent->ownerDocument->importNode($node, true);
$parent->appendChild($node);
}
}
Then you can simply do this:
然后你可以简单地这样做:
$elem = $dom->createElement('div');
appendHTML($elem, '<h1>Hello world</h1>');
回答by Gordon
You can use
您可以使用
Example:
例子:
// just some setup
$dom = new DOMDocument;
$dom->loadXml('<html><body/></html>');
$body = $dom->documentElement->firstChild;
// this is the part you are looking for
$template = $dom->createDocumentFragment();
$template->appendXML('<h1>This is <em>my</em> template</h1>');
$body->appendChild($template);
// output
echo $dom->saveXml();
Output:
输出:
<?xml version="1.0"?>
<html><body><h1>This is <em>my</em> template</h1></body></html>
If you want to import from another DOMDocument, replace the three lines with
如果要从另一个 DOMDocument 导入,请将三行替换为
$tpl = new DOMDocument;
$tpl->loadXml('<h1>This is <em>my</em> template</h1>');
$body->appendChild($dom->importNode($tpl->documentElement, TRUE));
Using TRUE
as the second argument to importNode
will do a recursive import of the node tree.
使用TRUE
作为第二个参数importNode
会做节点树的递归进口。
If you need to import (malformed) HTML, change loadXml
to loadHTML
. This will trigger the HTML parser of libxml (what ext/DOM uses internally):
如果您需要导入(格式错误的)HTML,请更改loadXml
为loadHTML
. 这将触发 libxml 的 HTML 解析器(ext/DOM 内部使用的):
libxml_use_internal_errors(true);
$tpl = new DOMDocument;
$tpl->loadHtml('<h1>This is <em>malformed</em> template</h2>');
$body->appendChild($dom->importNode($tpl->documentElement, TRUE));
libxml_use_internal_errors(false);
Note that libxml will try to correct the markup, e.g. it will change the wrong closing </h2>
to </h1>
.
请注意,libxml 将尝试更正标记,例如,它将错误的关闭更改</h2>
为</h1>
.
回答by Markus Zeller
As I do not want to struggle with XML, because it throws errors faster and I am not a fan of prefixing an @ to prevent error output. The loadHTML does the better job in my opinion and it is quite simple as that:
因为我不想与 XML 斗争,因为它会更快地抛出错误,而且我不喜欢在 @ 前加上前缀来防止错误输出。我认为 loadHTML 做得更好,而且非常简单:
$doc = new DOMDocument();
$div = $doc->createElement('div');
// use a helper to load the HTML into a string
$helper = new DOMDocument();
$helper->loadHTML('<a href="#">This is my HTML Link.</a>');
// now the magic!
// import the document node of the $helper object deeply (true)
// into the $div and append as child.
$div->appendChild($doc->importNode($helper->documentElement, true));
// add the div to the $doc
$doc->appendChild($div);
// final output
echo $doc->saveHTML();
回答by kenorb
Here is simple example by using DOMDocumentFragment:
这是使用DOMDocumentFragment 的简单示例:
$doc = new DOMDocument();
$doc->loadXML("<root/>");
$f = $doc->createDocumentFragment();
$f->appendXML("<foo>text</foo><bar>text2</bar>");
$doc->documentElement->appendChild($f);
echo $doc->saveXML();
Here is helper function for replacing DOMNode:
这是替换 DOMNode 的辅助函数:
/**
* Helper function for replacing $node (DOMNode)
* with an XML code (string)
*
* @var DOMNode $node
* @var string $xml
*/
public function replaceNodeXML(&$node, $xml) {
$f = $this->dom->createDocumentFragment();
$f->appendXML($xml);
$node->parentNode->replaceChild($f,$node);
}
Source: Some old "PHP5 Dom Based Template" article.
来源:一些旧的“基于 PHP5 Dom 的模板”文章。
And here is another suggestion posted by Pian0_M4nto use valueattribute as workaround:
这是Pian0_M4n发布的另一个建议,使用value属性作为解决方法:
$dom = new DomDocument;
// main object
$object = $dom->createElement('div');
// html attribute
$attr = $dom->createAttribute('value');
// ugly html string
$attr->value = "<div> this is a really html string ©</div><i></i> with all the © that XML hates!";
$object->appendChild($attr);
// jquery fix (or javascript as well)
$('div').html($(this).attr('value')); // and it works!
$('div').removeAttr('value'); // to clean-up
No ideal, but at least it works.
不理想,但至少它有效。
回答by hailong
Gumbo's code works perfectly! Just a little enhancement that adding the TRUE parameter so that it works with nested html snippets.
Gumbo 的代码完美运行!只是添加 TRUE 参数的一点改进,以便它与嵌套的 html 片段一起使用。
$node = $parent->ownerDocument->importNode($node);
$node = $parent->ownerDocument->importNode($node, **TRUE**);