我有以下XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<authors><![CDATA[ã ú ]]></authors>
</root>
我想将ú
转换为ú
。以下调用tidy
的方法不起作用。有人知道调用它的正确方法是什么?
tidy --preserve-entities no --output-encoding utf8 tmp1.xml > tmp2.xml
答案 0 :(得分:2)
CDATA部分,如
<![CDATA[ã ú]]>
等同于
<![CDATA[ã ú]]>
在CDATA部分中,&
,<
或>
等字符会失去其特殊含义,并按字面意思对待。所以上面的CDATA部分相当于
&#x00E3; &#x00FA;
您的转换不会“整理”您的XML文件,它实际上会更改字符数据。这就是为什么你不能用简单的工具进行你正在寻找的转换。此外,您通常不能盲目地应用正则表达式,因为您不想更改可能包含CDATA部分的XML文件的其他部分。
如果你真的想转换你所描述的文件,你应该使用XML库以你选择的脚本语言编写一个小程序。此程序应该只解码您希望转换发生的XML文件的那些部分中的实体。请参阅以下Perl脚本,例如:
use strict;
use XML::LibXML;
my $doc = XML::LibXML->new->parse_fh(\*STDIN);
# Process all text nodes within "authors" elements.
for my $authors_text ($doc->findnodes('//authors//text()')) {
my $text = $authors_text->data;
$text =~ s/&#x([0-9A-Fa-f]+);/chr(hex($1))/ge;
$authors_text->setData($text);
}
print $doc->toString;
答案 1 :(得分:0)
在java中使用泛型模式搜索和替换。
以下搜索&#
+可选x
(十六进制)+数字+ ;
。
String fillInNumericEntities(String xml) {
Pattern entityPattern = Pattern.compile("\\&#([Xx]?)([\\w]+);");
StringBuffer sb = new StringBuffer(xml.length());
Matcher m = entityPattern.matcher(xml);
while (m.find()) {
int numBase = m.group(1).isEmpty() ? 10 : 16;
String number = m.group(2);
try {
int codePoint = Integer.parseInt(number, numBase);
int[] codePoints = new int[] { codePoint };
String ch = new String(codePoints, 0, 1);
m.appendReplacement(sb, ch);
} catch (NumberFormatException e) {
}
}
m.appendTail(sb);
return sb.toString();
}
备注:浏览器可以是将特殊字符自动转换为数字实体的来源,尤其是在缺少HTML <form accept-charset="UTF-8">
的情况下。