5

我有一堆类似 HTML 的遗留文档。例如,它们看起来像 HTML,但有额外的组成标签,这些标签不是 HTML 的一部分

<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>

我需要解析这些文件。PHP 是唯一可用的工具。这些文档并不接近于格式良好的 XML。

我最初的想法是在 PHP DOMDocument 上使用 loadHTML 方法。但是,这些方法会阻塞 HTML 标签,并且会拒绝解析字符串/文件。

$oDom = new DomDocument();
$oDom->loadHTML("<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>");
//gives us
DOMDocument::loadHTML() [function.loadHTML]: Tag pseud-template invalid in Entity, line: 1 occured in ....

我能想出的唯一解决方案是使用字符串替换函数对文件进行预处理,该函数将删除无效标签并用有效的 HTML 标签替换它们(可能是带有标签名称 id 的跨度)。

有没有更优雅的解决方案?一种让 DOMDocument 知道其他标签被认为是有效的方法吗?PHP 是否有一个不同的、强大的 HTML 解析类/对象?

(如果不是很明显,我不认为正则表达式是一个有效的解决方案)

更新:假标签中的信息是这里目标的一部分,所以像 Tidy 这样的东西不是一个选择。此外,我正在寻找某种程度的(如果不是全部的话)格式良好的清理方法,这就是为什么我首先寻找 DomDocument 的 loadHTML 方法的原因。

4

6 回答 6

7

libxml_use_internal_errors您可以在加载文档时使用 , 禁止警告。例如。:

libxml_use_internal_errors(true);
$doc = new DomDocument();
$doc->loadHTML("<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>");
libxml_use_internal_errors(false);

如果出于某种原因,您需要访问警告,请使用libxml_get_errors

于 2010-08-31T21:22:45.777 回答
2

我想知道通过HTML Tidy传递“坏”的 HTML是否有助于作为第一遍?可能值得一看,如果您可以使文档格式正确,也许您可​​以使用 DomDocument 将其作为常规 XML 文件加载。

于 2008-09-15T20:50:03.753 回答
1

@Twan 您不需要 DOMDocument 的 DTD 来解析自定义 XML。只需使用DOMDocument->load(),只要 XML 格式正确,就可以读取它。

一旦你得到格式良好的文件,你就可以开始查看 XML 解析器,在此之前你是 SOL Lok Alejo 说的,你可以查看HTML TIDY,但它看起来是特定于 HTML 的,我不知道不知道它会如何与您的自定义元素一起使用。

我不认为正则表达式是一个有效的解决方案

在你有良好的形成之前,这可能是你唯一的选择。一旦你把文档放到那个阶段,那么你就可以清楚地使用 DOM 函数了。

于 2008-09-15T21:23:40.740 回答
1

看看 PHP Fit 端口中的 Parser。代码很干净,最初是为加载 Word 保存的脏 HTML 而设计的。它被配置为拉出表格,但很容易适应。

您可以在此处查看源代码:http: //gerd.exit0.net/pat/PHPFIT/PHPFIT-0.1.0/Parser.phps

单元测试将向您展示如何使用它: http: //gerd.exit0.net/pat/PHPFIT/PHPFIT-0.1.0/test/parser.phps

于 2008-09-15T21:31:16.977 回答
0

我对这个问题的快速而肮脏的解决方案是运行一个循环,将我的自定义标签列表与正则表达式匹配。正则表达式不会捕获其中包含另一个内部自定义标签的标签。

当存在匹配时,将调用处理该标记的函数并返回“已处理的 HTML”。如果该自定义标签在另一个自定义标签中,那么由于实际 HTML 被插入到子标签的位置,父标签就变成了无子标签​​,并且它将被正则表达式匹配并在循环的下一次迭代中处理。

当没有要匹配的无子自定义标签时,循环结束。总的来说,它是迭代的(一个while循环)而不是递归的。

于 2008-09-15T22:41:11.567 回答
0

@艾伦风暴

您对我其他答案的评论让我想到:

当您使用 DOMDocument 加载 HTML 文件时,它似乎会进行某种程度的清理:格式良好,但要求您的所有标签都是合法的 HTML 标签。我正在寻找可以做到前者的东西,但不是后者。(艾伦风暴)

在标签上运行正则表达式(对不起!),当它找到一个不是有效的 HTML 元素时,将其替换为您知道在任何文档中都不存在的有效元素(blink想到... ),并给它一个带有非法元素名称的属性值,以便之后可以将其切换回来。例如:

$code = str_replace("<pseudo-tag>", "<blink rel=\"pseudo-tag\">", $code);
// and then back again...
$code = preg_replace('<blink rel="(.*?)">', '<\1>', $code);

显然该代码行不通,但您明白了吗?

于 2008-09-16T04:28:17.880 回答