php - 使用 DOMDocument::saveHTML 避免自动关闭打开的 HTML 元素

标签 php html html-parsing domdocument

我的目标是将自定义数据属性添加到 divul containers 如果该容器使用特定类。我从包含有效 HTML(完整的 div 及其内容和结尾 </div> )或仅包含开头 div 的 HTML 片段开始(没有其内容和结尾 </div> )。

这是我可能会开始的内容示例:

<div id='gallery-7222-1' class='gallery galleryid-7222 gallery-columns-3 gallery-size-thumbnail'>

到目前为止,这是我尝试过的:

// grab all containers from the HTML.
$dom_doc = new DOMDocument();

/*
 * $html here can be the example I posted above.
 * LIBXML_HTML_NOIMPLIED and LIBXML_HTML_NODEFDTD are used
 * to avoid adding a doctype and wrapping the whole output in HTML tags.
 */
$dom_doc->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );

// Let's look for lists and divs.
$ul_tags  = $dom_doc->getElementsByTagName( 'ul' );
$div_tags = $dom_doc->getElementsByTagName( 'div' );

/*
 * Loop through each ul, and add the data.
 * I do more things in there, like checking for what class the ul has,
 * but I've simplified things here. 
 */
foreach ( $ul_tags as $ul_tag ) {
    $ul_tag->setAttribute( 'data-foo', 'bar' );
}

/*
 * Loop through each div, and add the data.
 * I do more things in there, like checking for what class the div has,
 * but I've simplified things here. 
 */
foreach ( $div_tags as $div_tag ) {
    $div_tag->setAttribute( 'data-foo', 'bar' );    
}

// Save our updated HTML.
$html = $dom_doc->saveHTML();

返回的 HTML 包括新的数据属性,还有一个结束 </div>我真的不想在这里。你可以在这里看到它: https://ideone.com/sVfAOn

我首先想到的是删除结尾的 </div>substr ,但我不能这样做: - 在某些情况下,我的原始 HTML 实际上包含一个我想保留的结束 div 标记。 - 有时我可能正在编辑一个包含 ul 的字符串相反。

我将如何停止 saveHTML()从这里变得那么聪明,从试图为我修复我的 HTML?

谢谢!

最佳答案

不,您不能说服 HTML 解析器不解析 HTML。最好的解决方案是首先重新考虑您获取数据的方法,并确保您不会获取碎片。

否则,您可以先尝试将其视为 XML 以查看它是否会中断:

<?php
libxml_use_internal_errors(true);
$dom_doc = new DOMDocument();
$remove = "";
// try loading it as xml
if (!$dom_doc->loadXml($html)) {
    // it failed, get the error message
    $err = libxml_get_last_error()->message ?? "";
    // is it because of an unclosed element?
    // find out which element it's breaking on
    if (preg_match("/end of data in tag (.*?) /", $err, $matches)) {
        $remove = "</$matches[1]>";
    }
}
$dom_doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

// do stuff

$html = str_replace($remove, "", $dom_doc->saveHTML());

当然,这假定您正在处理干净的 HTML,并且不会触发一堆其他错误。如果是这种情况,您需要通过 libxml_get_errors() 检查未闭合的元素错误。

关于php - 使用 DOMDocument::saveHTML 避免自动关闭打开的 HTML 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58096669/

相关文章:

python - BeautifulSoup 中带有 .get-operator 的 if 语句

c# - 如何在 html 字符串中找到匹配的结束标记?

php - 从 csv 文件导入数据的代码适用于 Windows,但不适用于 kali linux apache2。每个答案都已确定

css - 最大化窗口中的 HTML5 视频而不会溢出

java - 使用 HTML 解析器 (org.htmlparser) 提取和清理 HTML 片段

php - HTML 表的即时搜索栏,包含 MySQL 表中的信息

html标签获取不同的表单

php - Docx 到 pdf 使用 openoffice headless 方式太慢

javascript - 仅当按钮具有特定 ID 时,jQuery 保存/编辑按钮操作

php - 使用 PHP OOP 概念连接到 MySQL 数据库