对于超过3.0的Unicode版本,如何将Java字符串转换为xml实体?
要将java字符转换为xml实体,我可以对字符串中的每个字符执行以下操作:对于超过3.0的Unicode版本,如何将Java字符串转换为xml实体?,java,unicode,unicode-string,xml-entities,Java,Unicode,Unicode String,Xml Entities,要将java字符转换为xml实体,我可以对字符串中的每个字符执行以下操作: buf.append("&#x"+ Integer.toHexString(c | 0x10000).substring(1) +";"); 然而,根据其他stackoverflow问题,这只适用于Unicode 3.0 如果我使用UTF-8读取器读入一个字符串,那么该字符串可能包含通过Unicode 6.0实现的格式的字符(因为根据javadoc,Java7支持Unicode 6.0) 一旦我有了那个字符串,
buf.append("&#x"+ Integer.toHexString(c | 0x10000).substring(1) +";");
然而,根据其他stackoverflow问题,这只适用于Unicode 3.0
如果我使用UTF-8读取器读入一个字符串,那么该字符串可能包含通过Unicode 6.0实现的格式的字符(因为根据javadoc,Java7支持Unicode 6.0)
一旦我有了那个字符串,我怎么能把它写成xml实体呢?理想情况下,我会使用一些api,随着unicode新版本的推出,这些api将继续工作。或者您使用的术语不正确,或者这里有很多混淆
和#x
字符参考符号仅指定一个数字码点;它独立于任何读取器或解析器使用的Unicode版本
您的代码实际上只与Unicode 1.x兼容,因为它假定字符的数值小于216。从Unicode 2.0开始,这不是一个正确的假设。一些字符由单个Javachar
表示,而其他字符由两个Javachar
表示(称为)
我不确定什么是“UTF-8阅读器”。A只读取char
值,不知道UTF-8或任何其他字符集,除了使用A使用UTF-8编码(或特定字符集解码器使用的任何编码)将字节转换为字符
在任何情况下,读取器都不会解析XML和#x
字符引用符号。为此,必须使用XML解析器
Java已知的Unicode版本不会影响读取器或XML解析器,因为读取器或XML解析器不会以任何方式查阅Unicode数据库。这些字符在解析时仅被视为数值。在任何Unicode版本中,它们是否对应于指定的代码点都不会被考虑
最后,要将字符串写成XML,可以使用:
静态字符串toXML(字符串s){
格式化程序格式化程序=新格式化程序();
int len=s.length();
对于(int i=0;i126 | | c=='&'| | c=='){
格式(%x;”,c);
}否则{
格式化程序。格式(“%c”,c);
}
}
返回格式化程序.toString();
}
如您所见,没有依赖Unicode版本的代码,因为字符只是数值。每个数值是否为指定的Unicode码点并不相关
(我的第一个倾向是使用XMLStreamWriter类,但事实证明,使用非Unicode编码(如ISO-8859-1或US-ASCII)的XMLStreamWriter在Java 1.8.0_05中没有正确地将代理项对作为单字符实体输出。)或者您使用的术语不正确,或者这里有很多混乱
和#x
字符参考符号仅指定一个数字码点;它独立于任何读取器或解析器使用的Unicode版本
您的代码实际上只与Unicode 1.x兼容,因为它假定字符的数值小于216。从Unicode 2.0开始,这不是一个正确的假设。一些字符由单个Javachar
表示,而其他字符由两个Javachar
表示(称为)
我不确定什么是“UTF-8阅读器”。A只读取char
值,不知道UTF-8或任何其他字符集,除了使用A使用UTF-8编码(或特定字符集解码器使用的任何编码)将字节转换为字符
在任何情况下,读取器都不会解析XML和#x
字符引用符号。为此,必须使用XML解析器
Java已知的Unicode版本不会影响读取器或XML解析器,因为读取器或XML解析器不会以任何方式查阅Unicode数据库。这些字符在解析时仅被视为数值。在任何Unicode版本中,它们是否对应于指定的代码点都不会被考虑
最后,要将字符串写成XML,可以使用:
静态字符串toXML(字符串s){
格式化程序格式化程序=新格式化程序();
int len=s.length();
对于(int i=0;i126 | | c=='&'| | c=='){
格式(%x;”,c);
}否则{
格式化程序。格式(“%c”,c);
}
}
返回格式化程序.toString();
}
如您所见,没有依赖Unicode版本的代码,因为字符只是数值。每个数值是否为指定的Unicode码点并不相关
(我的第一个倾向是使用XMLStreamWriter类,但事实证明,使用非Unicode编码(如ISO-8859-1或US-ASCII)的XMLStreamWriter无法正确地将代理项对作为单字符实体输出,如Java 1.8.005)最初,Java支持Unicode 1.0,将字符长度设为16位,但Unicode 2.0引入了代理字符机制,以支持比16位允许的字符数更多的字符,因此Java字符串变成了UTF-16编码的字符串;这意味着一些字符需要两个Java字符来表示,它们被称为高代理字符和低代理字符 要知道字符串中的哪些字符实际上是高/低代理项对,可以使用
字符中的实用方法:
Character.isHighSurrogate(myChar); // returns true if myChar is a high surrogate
Character.isLowSurrogate(myChar); // same for low surrogate
Character.isSurrogate(myChar); // just to know if myChar is a surrogate
一旦您知道哪些字符是高代理或低代理,就需要使用以下方法将每对字符转换为unicode码点:
int codePoint = Character.toCodePoint(highSurrogate, lowSurrogate);
因为一段代码胜过千言万语,所以这是一个将xml字符引用替换为非us ascii c的示例方法
int codePoint = Character.toCodePoint(highSurrogate, lowSurrogate);
public static String replaceToCharEntities(String str) {
StringBuilder result = new StringBuilder(str.length());
char surrogate = 0;
for(char c: str.toCharArray()) {
// if char is a high surrogate, keep it to match it
// against the next char (low surrogate)
if(Character.isHighSurrogate(c)) {
surrogate = c;
continue;
}
// get codePoint
int codePoint;
if(surrogate != 0) {
codePoint = Character.toCodePoint(surrogate, c);
surrogate = 0;
} else {
codePoint = c;
}
// decide wether using just a char or a character reference
if(codePoint < 0x20 || codePoint > 0x7E || codePoint == '<'
|| codePoint == '>' || codePoint == '&' || codePoint == '"'
|| codePoint == '\'') {
result.append(String.format("&#x%x;", codePoint));
} else {
result.append(c);
}
}
return result.toString();
}