处理格式错误的XML
我正在处理perl中格式错误的XML,它是由上游进程生成的,我无法更改(这似乎是这里的一个常见问题)。但是,据我所知,XML的格式只有一种特殊的错误:它的属性值包含未转换的小于号,例如:处理格式错误的XML,xml,perl,Xml,Perl,我正在处理perl中格式错误的XML,它是由上游进程生成的,我无法更改(这似乎是这里的一个常见问题)。但是,据我所知,XML的格式只有一种特殊的错误:它的属性值包含未转换的小于号,例如: <tag v="< 2"> 我使用perl进行解析,当然,这会产生解析错误。我尝试过使用recover选项,它允许我进行解析,但当它遇到第一个解析错误时,它就会停止,因此我会以这种方式丢失数据 看来我有两个选择: 在解析输入XML之前修复它,可能使用正则表达式 找到一个更宽容的XML解析
<tag v="< 2">
我使用perl进行解析,当然,这会产生解析错误。我尝试过使用recover选项,它允许我进行解析,但当它遇到第一个解析错误时,它就会停止,因此我会以这种方式丢失数据
看来我有两个选择:
我倾向于选择1,因为我希望捕捉XML的任何其他错误。你推荐什么?如果#1,有人可以指导我使用正则表达式方法吗?一个选项是捕获异常,找出它们发生在输入中的什么地方,修复那里的输入,然后重试 下面是一个使用
XML::Twig
的快速、低效的概念验证脚本,因为我还没有弄清楚如何在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";
}
#/usr/bin/env perl
严格使用;
使用警告;
使用XML::Twig;
my$xml=q{};
而(1){
评估{
my$twig=XML::twig->new(
细枝处理程序=>{tag=>\&tag\u handler},
);
$twig->parse($xml);
1.
}最后,;
我的$err=$@;
我的($i)=($err=~/字节([0-9]+)/)
或者死得更惨;
substr($xml,$i,1)eq'我知道这不是您想要的答案-但是xml规范非常明确和严格
格式错误的XML是致命的。
如果它在验证器中不起作用,那么您的代码甚至不应该尝试“修复”它,就像您尝试自动“修复”某些程序代码一样
从:
致命错误
[定义:]一致性XML处理程序必须检测并向应用程序报告的一种错误。遇到致命错误后,处理程序可继续处理数据以搜索进一步的错误,并可向应用程序报告此类错误。为了支持错误更正,处理程序可从文档中生成未经处理的数据(混合字符数据和标记)可用于应用程序。但是,一旦检测到致命错误,处理器不得继续正常处理(即,它不得继续以正常方式将字符数据和有关文档逻辑结构的信息传递给应用程序)
特别是关于为什么:
我们希望XML使程序员能够编写可以在Web上传输并在大量台式机上执行的代码。然而,如果这些代码必须包括针对各种草率的最终用户实践的错误处理,那么它的大小必然会膨胀到像Netscape Navigator或Microsoft Internet Explorer那样无法处理的程度大小为兆字节,因此无法达到目的
如果你曾经尝试过为HTML组装一个解析器,你就会意识到为什么需要这样做——你最终为边缘情况、糟糕的标记嵌套、隐式标记闭包编写了如此多的处理程序,以至于你的代码从一开始就一团糟
而且因为这是我最喜欢的关于堆栈溢出的帖子——下面是一个例子,说明原因:
现在我意识到这并不总是一个选项,如果要求上游的“修复XML”是阻力最小的途径,那么您可能不会来这里。但是我仍然敦促您将其报告为XML源应用程序中的缺陷,并尽可能抵制以编程方式“修复”的压力,因为正如您正确理解的那样但是,当正确的答案是“从源头上解决问题”时,这是在给自己建立一个痛苦的世界
如果您真的在这条路上遇到了困难,您可以(正如所指出的那样)唯一的选择是捕获解析器失败的地方,然后检查并尝试在执行过程中进行修复。但是您找不到一个XML解析器可以为您做到这一点,因为从定义上讲,它是不可靠的
我建议你首先:
- 拿出一份说明书的副本,给要求你这么做的人看
- 向他们指出,我们制定标准的全部原因是为了促进互操作性
- 因此,通过做一些故意违反标准的事情,您正在冒业务风险——您正在创建可能有一天会神秘中断的代码,因为使用正则表达式或自动修复之类的东西是建立在一组可能不成立的假设中的
- 这里有一个有用的概念——解释一下,你正在通过自动修复而招致技术债务,而这其实不是你的问题
- 然后问他们是否愿意接受这种风险
- 如果他们确实认为这是一个可接受的风险,那么就继续做吧——你可能会发现它值得——有效地——忽略源数据看起来像XML的事实,并将其视为纯文本——使用正则表达式提取相关的数据行,等等
- 在对您未来的维护程序员的评论中加入道歉,解释是谁做出了这个决定以及为什么
也可以用作参考点:是未转义的它看起来并不总是。它也不总是“.后面的第一个字符。它可能类似于v=“3”标记不能以空格或数字开头。是否可能有v="我知道这通常不是一个选项,但正确的答案是“用卷起的XML规范副本击中上游的人的头部”。因此,我花了更多的时间来探讨这个问题,并写了一篇文章,因为在上游似乎无法改变行为,我同情OP的情况。你的观点是显而易见的我想我们都有过这样的经历——我不打算谴责任何人的错误