XML字符集仅限于以下内容:
[\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]
实体不得用于表示此集之外的字符。
我正在使用XML :: DOM从外部源解析一些XML数据文件。某些XML文件具有以& #xx;形式编码的不可打印字符。 (例如。
)导致解析器崩溃,因为它们无效。我试图找到一种简单的方法来删除这些无效字符。我试过了
$xml =~ s/(&#\c\c;)//g;
似乎不起作用。所以似乎没有任何相关的东西,我一直在网上搜索一段时间没有成功。
答案 0 :(得分:2)
我建议明确指定要删除的字符。
以下删除ascii范围中的不可打印字符实体。如果您想要覆盖所有不可打印的实体,就可以轻松扩展它。
另外,请注意@ikegami在问题评论中提到使用这样的正则表达式将破坏CDATA部分的内容。
use strict;
use warnings;
my $data = do {local $/; <DATA>};
# Allowed entities:
# [\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]
# Decimal Character Entities
$data =~ s/�*(?!(?:9|1[03])\b)(?:[12]?[0-9]|3[01]);//g;
# Hex Character Entities
$data =~ s/�*(?![9ADad]\b)1?[[:xdigit:]];//g;
print $data;
__DATA__
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<hex_character_entities>
<hex00>�	

</hex00>
<hex10></hex10>
<hex20> !...</hex20>
</hex_character_entities>
<decimal_character_entities>
<dec00>�	</dec00>
<dec10>  </dec10>
<dec20></dec20>
<dec30> !...</dec30>
</decimal_character_entities>
</root>
输出:
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<hex_character_entities>
<hex00>	

</hex00>
<hex10></hex10>
<hex20> !...</hex20>
</hex_character_entities>
<decimal_character_entities>
<dec0>	</dec0>
<dec1> </dec1>
<dec2></dec2>
<dec3> !...</dec3>
</decimal_character_entities>
</root>
答案 1 :(得分:2)
编写一个查找HTML中所有实体并使用/e
修饰符的子目录是有意义的,这样替换字符串就可以通过一个Perl代码块来提供。
此示例根据您自己的问题创建$html_chars
正则表达式模式,该模式将检查任何单个字符是否在范围内,然后使用它来测试字符串中所有字符实体的值。
请注意,由于#
修饰符允许空格和注释使正则表达式更具可读性,因此必须对模式中的哈希/x
进行转义。
我的测试字符串使用十进制和十六进制中所有ASCII字符代码的实体,您可以看到替换只删除除HT,LF和CR之外的控制字符。
use strict;
use warnings;
my $html_chars = qr/[\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/;
my $html = do {
local $/;
<DATA>;
};
$html =~ s{ ( &\# ( x[0-9A-Z]+ | [0-9]+ ) ; ) } {
my ($entity, $code) = ($1, $2);
$code = hex $code if $code =~ s/x//i;
chr($code) =~ $html_chars ? $entity : '';
}eixg;
print $html;
__DATA__
Decimal
�	  

 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~
Hex
�	


 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~
<强>输出强>
Decimal
	
 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~
Hex
	

 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~
答案 2 :(得分:0)
试试这个。
$ xml = ~s {&amp;#[0-9a-z] {1-2};} {} igs;
答案 3 :(得分:-1)
我会尝试使用\w
代替\c
。
以下为我生成了正确的结果:
my $xml = <<XML;
<?xml version="1.0" encoding="UTF-8" ?>
<outer>
<inner></inner>
</outer>
XML
$xml =~ s/&#\w{2};//g;