【问题标题】:How to tidy up things like ú in xml?如何整理xml中的ú之类的东西?
【发布时间】:2016-05-18 14:28:38
【问题描述】:
我有以下 XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<authors><![CDATA[ã ú ]]></authors>
</root>
我想将&#x00FA; 转换为ú。以下调用tidy 的方式不起作用。有谁知道正确的称呼方式是什么?
tidy --preserve-entities no --output-encoding utf8 tmp1.xml > tmp2.xml
【问题讨论】:
标签:
xml
unicode
utf-8
tidy
【解决方案1】:
类似的 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;
【解决方案2】:
在 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"> 缺失的情况下。