Sco*_*t B 106 php serialization domdocument
我是下面的函数,我在努力输出DOMDocument而没有在内容输出之前附加XML,HTML,body和p标签包装器.建议的修复:
$postarray['post_content'] = $d->saveXML($d->getElementsByTagName('p')->item(0));
Run Code Online (Sandbox Code Playgroud)
仅在内容中没有块级元素时才有效.但是,当它执行时,如下面的例子中的h1元素,saveXML的结果输出被截断为...
<p>如果你喜欢</ p>
我已经指出这篇文章可能是一种解决方法,但是我无法理解如何将它实现到这个解决方案中(参见下面的注释).
有什么建议?
function rseo_decorate_keyword($postarray) {
global $post;
$keyword = "Jasmine Tea"
$content = "If you like <h1>jasmine tea</h1> you will really like it with Jasmine Tea flavors. This is the last ocurrence of the phrase jasmine tea within the content. If there are other instances of the keyword jasmine tea within the text what happens to jasmine tea."
$d = new DOMDocument();
@$d->loadHTML($content);
$x = new DOMXpath($d);
$count = $x->evaluate("count(//text()[contains(translate(., 'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghjiklmnopqrstuvwxyz'), '$keyword') and (ancestor::b or ancestor::strong)])");
if ($count > 0) return $postarray;
$nodes = $x->query("//text()[contains(translate(., 'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghjiklmnopqrstuvwxyz'), '$keyword') and not(ancestor::h1) and not(ancestor::h2) and not(ancestor::h3) and not(ancestor::h4) and not(ancestor::h5) and not(ancestor::h6) and not(ancestor::b) and not(ancestor::strong)]");
if ($nodes && $nodes->length) {
$node = $nodes->item(0);
// Split just before the keyword
$keynode = $node->splitText(strpos($node->textContent, $keyword));
// Split after the keyword
$node->nextSibling->splitText(strlen($keyword));
// Replace keyword with <b>keyword</b>
$replacement = $d->createElement('strong', $keynode->textContent);
$keynode->parentNode->replaceChild($replacement, $keynode);
}
$postarray['post_content'] = $d->saveXML($d->getElementsByTagName('p')->item(0));
// $postarray['post_content'] = $d->saveXML($d->getElementsByTagName('body')->item(1));
// $postarray['post_content'] = $d->saveXML($d->getElementsByTagName('body')->childNodes);
return $postarray;
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*olo 198
所有这些答案现在都是错误的,因为从PHP 5.4开始,Libxml 2.6 loadHTML
现在有一个$option
参数,指示Libxml如何解析内容.
因此,如果我们使用这些选项加载HTML
$html->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
Run Code Online (Sandbox Code Playgroud)
什么时候saveHTML()
会有,没有doctype
,没有<html>
,没有<body>
.
LIBXML_HTML_NOIMPLIED
关闭自动添加隐含的html/body元素LIBXML_HTML_NODEFDTD
可防止在找不到默认文档类型时添加默认文档类型.
有关Libxml参数的完整文档在这里
(请注意,loadHTML
文档说需要Libxml 2.6,但LIBXML_HTML_NODEFDTD
仅在Libxml 2.7.8 LIBXML_HTML_NOIMPLIED
中可用,并且在Libxml 2.7.7中可用)
Ale*_*lex 69
使用loadHTML()加载文档后直接删除节点:
# remove <!DOCTYPE
$doc->removeChild($doc->doctype);
# remove <html><body></body></html>
$doc->replaceChild($doc->firstChild->firstChild->firstChild, $doc->firstChild);
Run Code Online (Sandbox Code Playgroud)
Jon*_*nah 18
请saveXML()
改为使用,并将documentElement作为参数传递给它.
$innerHTML = '';
foreach ($document->getElementsByTagName('p')->item(0)->childNodes as $child) {
$innerHTML .= $document->saveXML($child);
}
echo $innerHTML;
Run Code Online (Sandbox Code Playgroud)
http://php.net/domdocument.savexml
lon*_*day 15
一个巧妙的技巧是使用loadXML
然后saveHTML
.在html
和body
标签插入到load
舞台,没有save
舞台.
$dom = new DOMDocument;
$dom->loadXML('<p>My DOMDocument contents are here</p>');
echo $dom->saveHTML();
Run Code Online (Sandbox Code Playgroud)
请注意,这有点hacky,你应该使用Jonah的答案,如果你能让它工作.
小智 14
使用DOMDocumentFragment
$html = 'what you want';
$doc = new DomDocument();
$fragment = $doc->createDocumentFragment();
$fragment->appendXML($html);
$doc->appendChild($fragment);
echo $doc->saveHTML();
Run Code Online (Sandbox Code Playgroud)
Sup*_*Cat 13
最佳答案的问题LIBXML_HTML_NOIMPLIED
是不稳定.
它可以重新排序元素(特别是将顶部元素的结束标记移动到文档的底部),添加随机p
标记,以及可能还有其他各种问题[1].它可能会为您删除html
和body
标记,但代价是不稳定的行为.在制作中,那是一面红旗.简而言之:
不要用LIBXML_HTML_NOIMPLIED
.相反,使用substr
.
想一想.文件的长度<html><body>
和</body></html>
固定的两端 - 它们的尺寸永远不会改变,它们的位置也不会改变.这允许我们用它substr
来切掉它们:
$dom = new domDocument;
$dom->loadHTML($html, LIBXML_HTML_NODEFDTD);
echo substr($dom->saveHTML(), 12, -15); // the star of this operation
Run Code Online (Sandbox Code Playgroud)
(这不是最终的解决方案!请参阅下面的完整答案,继续阅读上下文)
我们12
从文件的开头切掉了因为<html><body>
= 12个字符(<<>>+html+body
= 4 + 4 + 4),然后我们往后退了15个,因为\n</body></html>
= 15个字符(\n+//+<<>>+body+html
= 1 + 2 + 4 + 4 + 4)
请注意,我仍然使用LIBXML_HTML_NODEFDTD
省略!DOCTYPE
包含.首先,这简化了substr
HTML/BODY标记的删除.其次,我们不会删除doctype,substr
因为我们不知道' default doctype
'总是会是固定长度的东西.但是,最重要的是,LIBXML_HTML_NODEFDTD
阻止DOM解析器将非HTML5文档类型应用于文档 - 这至少会阻止解析器处理它不能识别为松散文本的元素.
我们知道HTML/BODY标签具有固定的长度和位置这一事实,并且我们知道在LIBXML_HTML_NODEFDTD
没有某种类型的弃用通知的情况下永远不会删除常量,因此上述方法应该很好地应用到未来,但是 ......
...唯一需要注意的是DOM实现可能会改变HTML/BODY标记放置在文档中的方式 - 例如,删除文档末尾的换行符,在标记之间添加空格或添加换行符.
这可以通过搜索开关标记的位置来解决body
,并使用这些偏移来修剪我们的长度.我们分别使用strpos
和strrpos
从前面和后面找到偏移量:
$dom = new domDocument;
$dom->loadHTML($html, LIBXML_HTML_NODEFDTD);
$trim_off_front = strpos($dom->saveHTML(),'<body>') + 6;
// PositionOf<body> + 6 = Cutoff offset after '<body>'
// 6 = Length of '<body>'
$trim_off_end = (strrpos($dom->saveHTML(),'</body>')) - strlen($dom->saveHTML());
// ^ PositionOf</body> - LengthOfDocument = Relative-negative cutoff offset before '</body>'
echo substr($dom->saveHTML(), $trim_off_front, $trim_off_end);
Run Code Online (Sandbox Code Playgroud)
最后,重复最后的,面向未来的答案:
$dom = new domDocument;
$dom->loadHTML($html, LIBXML_HTML_NODEFDTD);
$trim_off_front = strpos($dom->saveHTML(),'<body>') + 6;
$trim_off_end = (strrpos($dom->saveHTML(),'</body>')) - strlen($dom->saveHTML());
echo substr($dom->saveHTML(), $trim_off_front, $trim_off_end);
Run Code Online (Sandbox Code Playgroud)
没有doctype,没有html标签,没有body标签.我们只能希望DOM解析器很快就能获得一层新的涂料,我们可以更直接地消除这些不需要的标签.
Vix*_*xxs 12
这是2017年,对于2011年的问题,我不喜欢任何答案.很多正则表达式,大类,loadXML等......
解决已知问题的简单解决方案:
$dom = new DOMDocument();
$dom->loadHTML( '<html><body>'.mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8').'</body></html>' , LIBXML_HTML_NODEFDTD);
$html = substr(trim($dom->saveHTML()),12,-14);
Run Code Online (Sandbox Code Playgroud)
简单,简单,坚固,快速.此代码适用于HTML标记和编码,如:
$html = '<p>äöü</p><p>ß</p>';
Run Code Online (Sandbox Code Playgroud)
如果有人发现错误,请告诉我,我会自己使用.
编辑,其他有效的选项,可以正常工作(非常类似于已经给出的):
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$saved_dom = trim($dom->saveHTML());
$start_dom = stripos($saved_dom,'<body>')+6;
$html = substr($saved_dom,$start_dom,strripos($saved_dom,'</body>') - $start_dom );
Run Code Online (Sandbox Code Playgroud)
你可以自己添加身体,以防止任何奇怪的东西.
Thirt选项:
$mock = new DOMDocument;
$body = $dom->getElementsByTagName('body')->item(0);
foreach ($body->childNodes as $child){
$mock->appendChild($mock->importNode($child, true));
}
$html = trim($mock->saveHTML());
Run Code Online (Sandbox Code Playgroud)
hak*_*kre 10
我在俱乐部有点迟了但不想不分享我发现的方法.首先,我已经为loadHTML()提供了正确的版本来接受这些不错的选项,但是LIBXML_HTML_NOIMPLIED
在我的系统上无效.用户也会报告解析器的问题(例如此处和此处).
我创建的解决方案实际上非常简单.
要加载的HTML放在一个<div>
元素中,因此它有一个容器,包含要加载的所有节点.
然后从文档中删除此容器元素(但它的DOMElement仍然存在).
然后删除文档中的所有直接孩子.这包括任何添加<html>
,<head>
和<body>
标签(有效LIBXML_HTML_NOIMPLIED
选项),以及该<!DOCTYPE html ... loose.dtd">
声明(有效LIBXML_HTML_NODEFDTD
).
然后,容器的所有直接子项再次添加到文档中,并可以输出.
$str = '<p>Lorem ipsum dolor sit amet.</p><p>Nunc vel vehicula ante.</p>';
$doc = new DOMDocument();
$doc->loadHTML("<div>$str</div>");
$container = $doc->getElementsByTagName('div')->item(0);
$container = $container->parentNode->removeChild($container);
while ($doc->firstChild) {
$doc->removeChild($doc->firstChild);
}
while ($container->firstChild ) {
$doc->appendChild($container->firstChild);
}
$htmlFragment = $doc->saveHTML();
Run Code Online (Sandbox Code Playgroud)
XPath像往常一样工作,只需要注意现在有多个文档元素,所以不是单个根节点:
$xpath = new DOMXPath($doc);
foreach ($xpath->query('/p') as $element)
{ # ^- note the single slash "/"
# ... each of the two <p> element
Run Code Online (Sandbox Code Playgroud)
好吧,我找到了一个更优雅的解决方案,但它很乏味:
$d = new DOMDocument();
@$d->loadHTML($yourcontent);
...
// do your manipulation, processing, etc of it blah blah blah
...
// then to save, do this
$x = new DOMXPath($d);
$everything = $x->query("body/*"); // retrieves all elements inside body tag
if ($everything->length > 0) { // check if it retrieved anything in there
$output = '';
foreach ($everything as $thing) {
$output .= $d->saveXML($thing);
}
echo $output; // voila, no more annoying html wrappers or body tag
}
Run Code Online (Sandbox Code Playgroud)
好吧,希望这不会遗漏任何内容并对某人有所帮助?
归档时间: |
|
查看次数: |
49582 次 |
最近记录: |