错误容忍PHP中的HTML / XML / SGML解析

时间:2008-09-15 20:41:29

标签: php html xml parsing

我有一堆类似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的span)名称)。

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

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

更新:假标签中的信息是此处目标的一部分,因此像Tidy这样的东西不是一个选项。另外,我正在处理一些事情,如果不是所有的话,对我进行良好的清理,这就是为什么我首先要看DomDocument的loadHTML方法。

6 个答案:

答案 0 :(得分:6)

您可以在加载文档时使用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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

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

  

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

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

答案 3 :(得分: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

答案 4 :(得分:0)

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

当匹配时,将调用处理该标记的函数并返回“已处理的HTML”。如果自定义标记位于另一个自定义标记内,则父级变为无子标记,因为插入实际HTML代替子级,并且它将由正则表达式匹配并在循环的下一次迭代处理。

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

答案 5 :(得分:0)

@Alan Storm

你对我的另一个回答的评论让我思考:

  

当您使用DOMDocument加载HTML文件时,它似乎做了一定程度的清理:良好的格式,但是要求所有标记都是合法的HTML标记。我正在寻找能够做到前者的东西,但不是后者。 (艾伦风暴)

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

blink
很明显,代码不起作用,但你得到了一般的想法?