如何从Perl中的字符串中删除无效的XML字符?

And*_*ewR 10 xml perl

我正在寻找在将字符串写入XML文件之前从字符串中删除无效字符的标准,批准和强大的方法.我在这里谈论的是包含退格(^ H)和换页字符等的文本块.

成为这样一个标准库/模块的功能,但我不能找到它.

我正在使用XML :: LibXML构建一个DOM树,然后我将其序列化到磁盘.

小智 7

删除无效的xml-1.0字符的完整正则表达式是:

# #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
$str =~ s/[^\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]//go;
Run Code Online (Sandbox Code Playgroud)

对于xml-1.1,它是:

# allowed: [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
$str =~ s/[^\x01-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]//go;
# restricted:[#x1-#x8][#xB-#xC][#xE-#x1F][#x7F-#x84][#x86-#x9F]
$str =~    s/[\x01-\x08\x0B-\x0C\x0E-\x1F\x7F-\x84\x86-\x9F]//go;
Run Code Online (Sandbox Code Playgroud)


Nic*_*son 6

几乎所有人都说过,使用正则表达式.说实话,它不够复杂,不值得添加到库中.使用替换预处理文本.

您对上面的换行符的评论表明格式化对您来说非常重要,因此您可能必须确切地决定要替换某些字符.

XML规范中明确定义了无效字符列表(例如,http://www.w3.org/TR/REC-xml/#charsets).不允许的字符是ASCII控制字符栏回车,换行和制表符.所以,你正在看一个29个字符的正则表达式字符类.那肯定不是太糟糕.

就像是:

$text =~ s/[\x00-\x08 \x0B \x0C \x0E-\x19]//g;
Run Code Online (Sandbox Code Playgroud)

应该这样做.


Jua*_*rro 5

我找到了一个解决方案,但它使用iconv命令而不是perl.

$ iconv -c -f UTF-8 -t UTF-8 invalid.utf8 > valid.utf8
Run Code Online (Sandbox Code Playgroud)

以上基于正则表达式给出的解决方案不起作用!! ,请考虑以下示例:

$ perl -e 'print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\x{A0}\x{A0}</root>"' > invalid.xml
$ perl -e 'use XML::Simple; XMLin("invalid.xml")'
invalid.xml:2: parser error : Input is not proper UTF-8, indicate encoding !
Bytes: 0xA0 0xA0 0x3C 0x2F
$ perl -ne 's/[^\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]//go; print' invalid.xml > valid.xml
$ perl -e 'use XML::Simple; XMLin("valid.xml")'
invalid.xml:2: parser error : Input is not proper UTF-8, indicate encoding !
Bytes: 0xA0 0xA0 0x3C 0x2F
Run Code Online (Sandbox Code Playgroud)

事实上,这两个文件invalid.xmlvalid.xml相同的.

问题是"\ x20-\x {D7FF}"范围匹配那些unicode字符的有效表示,但不匹配例如无效字符序列"\ x {A0}\x {A0}".