我正在解析外部方提供给我的一些XML,他们绝对不会改变它们;这些讨厌的XML包含CDATA部分内的HTML和XML :: Parser扼流圈。
除了完全剥离CDATA之外,还有什么方法可以解决这个问题吗?
修改
原始错误是"格式不正确(令牌无效)"。
对不起,我没有立即发布测试用例。经过一些研究后,我出于某种原因确信CDATA内部应该是有效的XML,所以我发布了这个问题。
感谢@ikegami工作测试用例和@mirod非常可能且不明显的原因 - 编码不匹配。
下面发布了真正的理由作为答案。
答案 0 :(得分:4)
XML :: Parser不应该阻塞正确的CDATA部分。基本上任何东西都在CDATA内,除了]]>
,只要它的字符数据,这意味着没有随机二进制,这似乎不是你的情况,并且编码中没有数据与文档声明(显式或隐式)的不兼容。这可能是问题所在。
如果您的问题是文档中没有编码声明,我不会感到惊讶,因此解析器假定它是UTF-8,但HTML数据是latin-1或windows-1252 ,当读取为UTF-8时,会生成无效的字符。
根据您的数据,您可以强制编码为latin1,如果XML数据本身不是特定的UTF-8,请使用XML :: Parser选项ProtocolEncoding => 'ISO-8859-1'
,或者您可能需要转换CDATA部分中文本的编码,预解析。
请注意,使用不同的解析器可能没有用,因为设计XML解析器应该在遇到格式不正确的XML时停止
答案 1 :(得分:3)
XML :: Parser非常好地处理CDATA块。也许您需要更新XML :: Parser或基础expat
库,或者您的问题可能在其他地方。很难说,因为你没有证明你的问题。
use strict;
use warnings;
use feature qw( say );
use Data::Dumper qw( Dumper );
use XML::Parser qw( );
sub f {
local $Data::Dumper::Indent = 0;
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Useqq = 1;
return Dumper($_[0]);
}
my $parser = XML::Parser->new(
Handlers => {
Start => sub { say "Start of $_[1]"; },
End => sub { say "End of $_[1]"; },
Char => sub { say "Char: " . f($_[1]); },
},
);
$parser->parse(<<'__EOI__');
<root>
<![CDATA[
<html>
<foo>test > test</foo><br>
</html>
]]>
</root>
__EOI__
Start of root
Char: "\n"
Char: "\n"
Char: " <html>"
Char: "\n"
Char: " <foo>test > test</foo><br>"
Char: "\n"
Char: " </html>"
Char: "\n"
Char: "\n"
End of root
答案 2 :(得分:0)
好吧,在最小化我的XML后,我能够跟踪这些错误的原因:它是一个垂直标签特殊符号。
疯狂!
我能够使用此代码段修复我的文件:
perl -CSDA -pe 'tr/\x00-\x08\x0B\x0C\x0E-\x19//d' bad.xml > good.xml