Java 发现无效的XML字符(Unicode:0xc)
使用Java DOM解析器分析XML文件会导致:Java 发现无效的XML字符(Unicode:0xc),java,xml,dom,xml-parsing,Java,Xml,Dom,Xml Parsing,使用Java DOM解析器分析XML文件会导致: [Fatal Error] os__flag_8c.xml:103:135: An invalid XML character (Unicode: 0xc) was found in the element content of the document. org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0xc) was found in the element
[Fatal Error] os__flag_8c.xml:103:135: An invalid XML character (Unicode: 0xc) was found in the element content of the document.
org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0xc) was found in the element content of the document.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
即使将数据封装在CDATA块中,XML文档中也允许使用一些字符 如果您生成了文档,则需要对其进行实体编码或删除。如果您有一个错误文档,您应该在解析它之前去掉这些字符 参见本帖中的dolmens答案: 他链接到这篇文章的地方:
基本上,0x20以下的所有字符都是不允许的,除了0x9(制表符)、0xA(CR?)和0xD(LF?)字符0x0C在XML 1.0中是无效的,但可能是无效的。因此,除非xml文件在序言中将版本指定为1.1,否则它完全无效,您应该向该文件的生产者投诉。我遇到了一个类似的问题,xml包含控制字符。查看代码后,我发现一个不推荐使用的类StringBufferInputStream用于读取字符串内容
我将它改为ByteArrayInputStream,它工作得很好。每当xml中出现无效的xml字符时,就会出现这样的错误。当你在notepad++中打开它时,它看起来像VT、SOH、FF,就像这些是无效的xml字符一样。我使用的是xml版本1.0,在按模式将文本数据输入数据库之前,我验证了文本数据
Pattern p = Pattern.compile("[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFF]+");
retunContent = p.matcher(retunContent).replaceAll("");
它将确保不会在xml中输入无效的特殊字符{
public String stripNonValidXMLCharacters(String in) {
StringBuffer out = new StringBuffer(); // Used to hold the output.
char current; // Used to reference the current character.
if (in == null || ("".equals(in))) return ""; // vacancy test.
for (int i = 0; i < in.length(); i++) {
current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen.
if ((current == 0x9) ||
(current == 0xA) ||
(current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF)))
out.append(current);
}
return out.toString();
}
StringBuffer out=new StringBuffer();//用于保存输出。
char current;//用于引用当前字符。
if(in==null | |(“”.equals(in)))返回“”;//空缺测试。
对于(int i=0;ipublic class InvalidXmlCharacterFilter extends FilterReader {
protected InvalidXmlCharacterFilter(Reader in) {
super(in);
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
int read = super.read(cbuf, off, len);
if (read == -1) return read;
for (int i = off; i < off + read; i++) {
if (!XMLChar.isValid(cbuf[i])) cbuf[i] = '?';
}
return read;
}
}
对于将字节数组读入字符串并尝试使用JAXB转换为对象的人,可以通过从字节数组创建字符串来添加“iso-8859-1”编码,如下所示:
InputStream fileStream = new FileInputStream(xmlFile);
Reader reader = new BufferedReader(new InputStreamReader(fileStream, charset));
InvalidXmlCharacterFilter filter = new InvalidXmlCharacterFilter(reader);
InputSource is = new InputSource(filter);
xmlReader.parse(is);
String=新字符串(字节[]输入,“iso-8859-1”)
这将取代JAXB可以处理的冲突字节到单字节编码。显然,此解决方案仅用于解析xml。所有这些答案似乎都假设用户生成的是错误的xml,而不是从gSOAP接收的,gSOAP应该知道得更清楚!今天,我遇到了一个类似的错误: 路径为[/***]的上下文中Servlet[remoting]的
Servlet.service()引发了异常[请求处理失败;嵌套异常为java.lang.RuntimeException:buildDocument失败],其根本原因是
org.xml.sax.saxpasseeption;行号:19;列号:91;在属性“text”的值中发现无效的xml字符(Unicode:0xc),元素为“label”。
在我第一次遇到这个错误后,我用手重新键入了整行,这样就没有办法让一个特殊的字符潜入,记事本++也没有显示任何不可打印的字符(黑白相间),尽管如此,我还是一次又一次地犯下同样的错误 当我查看我所做的与以前不同的事情时,发现在结束/>之前增加了一个空格(正如我所听说的那样,对于较旧的解析器,建议使用此空格,但根据XML标准,它不会有任何区别):
当我移除空间时:
一切都很顺利
因此,这肯定是一条误导性的错误消息。+1-基本上,OP的问题是他试图解析的XML文件无效。实体编码无法工作;XML文本中根本不允许该值。如果您可以编写一个基于正则表达式的解决方案,该解决方案将是健壮的,而fastregex通常速度较慢,则上述代码将更快,因为它只使用这一个thingNow而不是
StringBuffer
使用StringBuilder
,因为它更快(不需要对象监视器/未同步)。您提供的模式是正确的,但没有按原样编译。您需要一些转义。正确的是pattern.compile(“[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFF]+”
然后,可能是内存访问问题破坏了内容。嗨,瓦迪姆,你的想法很好。XMLChar的来源是什么?
InputStream fileStream = new FileInputStream(xmlFile);
Reader reader = new BufferedReader(new InputStreamReader(fileStream, charset));
InvalidXmlCharacterFilter filter = new InvalidXmlCharacterFilter(reader);
InputSource is = new InputSource(filter);
xmlReader.parse(is);