xml中需要过滤的字符分为两类,一类是不允许出现在xml中的字符,这些字符不在xml的定义范围之内。另一类是xml自身要使用的字符,如果内容中有这些字符则需被替换成别的字符。
第一类字符
第二类字符
xml支持的字符范围
Character Range
[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
意思是xml支持的字符范围是任何unicode字符,排除surrogate blocks(代理块), FFFE和 FFFF.
其中0xD800 至 0xDBFF(高代理high surrogate) 和 0xDC00 至 0xDFFF(低代理low surrogate)被称为surrogate blocks(代理块)
代理块是为了表示增补字符 增补字符是在 [#x10000-#x10FFFF] 范围之间的字符
增补字符是扩展16位unicode不能表示的字符。Unicode 最初设计是作为一种固定宽度的 16 位字符编码。16 位编码的所有 65,536 个字符并不能完全表示全世界所有正在使用或曾经使用的字符。于是,Unicode 标准扩展到包含多达 1,112,064 个字符,这些扩展字符就是增补字符。
XMLCheck用于检查xml文件中包含非法xml字符的个数。
使用方法 XMLCheck filename
import java.io.*;
public class XMLCheck {
/**
* @author lxn
*
*/
public static void main(String[] args) throws IOException{
if(args.length == 0)
{
System.out.print("Usage: XMLCheck filename");
return;
}
File xmlFile = new File(args[0]);
if(!xmlFile.exists())
{
System.out.print("File not exist");
return;
}
//输入xml文件
BufferedReader in = new BufferedReader(new FileReader(xmlFile));
String s;
StringBuilder xmlSb = new StringBuilder();
//xml文件转换成String
while((s = in.readLine())!=null)
xmlSb.append(s+"\n");
in.close();
String xmlString = xmlSb.toString();
// TODO Auto-generated method stub
//无特殊字符的
//int i = checkCharacterData("<?xml version=\"1.0\" encoding=\"gbk\"?><CC>卡号</CC>");
//有特殊字符的
//int i = checkCharacterData("<?xml version=\"1.0\" encoding=\"gbk\"?><CC>\u001E卡号</CC>");
int errorChar = checkCharacterData(xmlString);
System.out.println("This XML file contain "+errorChar+" errorChar.");
}
//判断字符串中是否有非法字符
public static int checkCharacterData(String text){
int errorChar=0;
if(text==null){
return errorChar;
}
char[] data = text.toCharArray();
for(int i=0,len=data.length;i<len;i++){
char c = data[i];
int result=c;
//先判断是否在代理范围(surrogate blocks)
//增补字符编码为两个代码单元,
//第一个单元来自于高代理(high surrogate)范围(0xD800 至 0xDBFF),
//第二个单元来自于低代理(low surrogate)范围(0xDC00 至 0xDFFF)。
if(result>=0xD800 && result<=0xDBFF){
//解码代理对(surrogate pair)
int high = c;
try{
int low=text.charAt(i+1);
if(low<0xDC00||low>0xDFFF){
char ch=(char)low;
}
//unicode说明定义的算法 计算出增补字符范围0x10000 至 0x10FFFF
//即若result是增补字符集,应该在0x10000到0x10FFFF之间,isXMLCharacter中有判断
result = (high-0xD800)*0x400+(low-0xDC00)+0x10000;
i++;
}
catch(Exception e){
e.printStackTrace();
}
}
if(!isXMLCharacter(result)){
errorChar++;
}
}
return errorChar;
}
private static boolean isXMLCharacter(int c){
//根据xml规范中的Character Range检测xml不支持的字符
if(c <= 0xD7FF){
if(c >= 0x20)return true;
else{
if (c == '\n') return true;
if (c == '\r') return true;
if (c == '\t') return true;
return false;
}
}
if (c < 0xE000) return false; if (c <= 0xFFFD) return true;
if (c < 0x10000) return false; if (c <= 0x10FFFF) return true;
return false;
}
}