我在perl中处理格式错误的XML,这是由我无法改变的上游流程生成的(这似乎是一个常见的问题)。但是,就我所见,XML只是以一种特殊方式出现格式错误:它的属性值包含非转义符号,例如:
<tag v="< 2">
我使用带有XML::LibXML的perl进行解析,当然,这会产生解析错误。我尝试过使用recover选项,它允许我解析,但它只是在遇到第一个解析错误时停止,所以我就是这样丢失数据。
似乎我有两个一般选择:
我倾向于选项1,因为我想抓住XML的任何其他错误。你会推荐什么?如果#1,有人可以指导我完成正则表达式吗?
答案 0 :(得分:8)
我知道这不是你想要的答案 - 但XML规范非常明确和严格。
格式错误的XML是致命的。
如果它在验证器中不起作用,那么您的代码甚至不应该尝试“修复”它,而不是您尝试并自动“修复”某些程序代码。
致命错误 [定义:]符合XML处理器必须检测并向应用程序报告的错误。在遇到致命错误之后,处理器可以继续处理数据以搜索进一步的错误并且可以将这样的错误报告给应用程序。为了支持纠正错误,处理器可以从文档中获得未处理的数据(具有混合的字符数据和标记),以供应用程序使用。但是,一旦检测到致命错误,处理器就不能继续正常处理(即,它不能继续以正常方式将字符数据和有关文档逻辑结构的信息传递给应用程序)。
特别是关于原因的评论:"Draconian" error-handling
我们希望XML能够让程序员编写可以通过Web传输并在大量桌面上执行的代码。但是,如果此代码必须包含针对各种草率最终用户实践的错误处理,则必须将其大小扩展到与Netscape Navigator或Microsoft Internet Explorer一样大小为数十兆字节的程度。打败目的。
如果您曾尝试将HTML解析器组合在一起,您将会发现为什么它需要这样 - 您最终会为边缘情况编写SO MANY处理程序,错误的标记嵌套,以及您的代码隐含标记关闭从一开始就是一团糟。
因为这是我在Stack Overflow上最喜欢的帖子 - 这是一个原因的例子:RegEx match open tags except XHTML self-contained tags
现在我感谢这并不总是一个选择,如果要求你的上游'修复你的XML'是阻力最小的路径,你可能不会来这里。但是我仍然会敦促你把它作为XML原始应用程序中的缺陷报告,并尽可能地抵制以编程方式'修复'的压力 - 因为正如你正确地想到的那样,它正在构建一个痛苦的世界,当正确的答案是“在源头修复问题”。
如果你真的被困在这条路上,你可以 - 正如Sinan Ünür所指出的那样 - 你唯一的选择是陷阱解析器失败的地方,然后检查并尝试修复。但是你找不到一个能够为你做的XML解析器,因为那个按照定义的那个解析了。
我首先建议:
也可能有用作参考点:Which character should not be set as values in XML file
答案 1 :(得分:7)
一个选项是捕获异常,找出它们在输入中的位置,在那里修复输入,然后重试。
以下是使用XML::Twig
的快速,低效的概念验证脚本,因为我还没有弄清楚如何构建&amp;在Windows上从头开始安装libxml2。
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $xml = q{ <tag v="< 2"/> };
while ( 1 ) {
eval {
my $twig = XML::Twig->new(
twig_handlers => { tag => \&tag_handler },
);
$twig->parse( $xml );
1;
} and last;
my $err = $@;
my ($i) = ($err =~ /byte ([0-9]+)/)
or die $err;
substr($xml, $i, 1) eq '<'
or die $err;
$xml = substr($xml, 0, $i) . '<' . substr($xml, $i + 1);
}
sub tag_handler {
my (undef, $elt) = @_;
print $elt->att('v'), "\n";
}
我写了更多关于这个on my blog。