2011-04-28 95 views
9

我正在使用编码“UTF-8”将对象编组为XML文件。它成功生成文件。但是,当我尝试解组回来,有一个错误:Unmarshall期间XML字符无效

An invalid XML character (Unicode: 0x{2}) was found in the value of attribute "{1}" and element is "0"

的字符是0x1A的或\ u001a,这是XML的UTF-8有效的,但非法的。 JAXB中的Marshaller允许将此字符写入XML文件,但Unmarshaller无法解析它。我试图使用另一种编码(UTF-16,ASCII等),但仍然错误。

常见的解决方案是在XML解析之前删除/替换此无效字符。但是如果我们需要这个角色,那么在解组之后如何获得原始角色呢?


在寻找此解决方案时,我想在取消编组之前用替代字符(例如dot =“。”)替换无效字符。

我创造了这个类:

public class InvalidXMLCharacterFilterReader extends FilterReader { 

    public static final char substitute = '.'; 

    public InvalidXMLCharacterFilterReader(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 -1; 

     for (int readPos = off; readPos < off + read; readPos++) { 
      if(!isValid(cbuf[readPos])) { 
        cbuf[readPos] = substitute; 
      } 
     } 

     return readPos - off + 1; 
    } 

    public boolean isValid(char c) { 
     if((c == 0x9) 
       || (c == 0xA) 
       || (c == 0xD) 
       || ((c >= 0x20) && (c <= 0xD7FF)) 
       || ((c >= 0xE000) && (c <= 0xFFFD)) 
       || ((c >= 0x10000) && (c <= 0x10FFFF))) 
     { 
      return true; 
     } else 
      return false; 
    } 
} 

那么这就是我如何读解组文件:

FileReader fileReader = new FileReader(this.getFile()); 
Reader reader = new InvalidXMLCharacterFilterReader(fileReader); 
Object o = (Object)um.unmarshal(reader); 

不知何故,读者不替换我想要的字符无效字符。它导致错误的XML数据不能被解组。我的InvalidXMLCharacterFilterReader类有什么问题吗?

+0

您可以检查XML标题,编码后在哪个字符集中定义它?它是UTF-8吗? – JMelnik 2011-04-28 07:33:03

+0

在XML标题中没有定义字符集,只有<?xml version =“1.0”?>。但我已经把这个:'m.setProperty(Marshaller.JAXB_ENCODING,“UTF-8”);' – oliverwood 2011-04-28 07:52:23

回答

1

我觉得主要的问题是在编组期间逃脱非法字符。类似的东西被提到here,你可以试试看。

提供改变编码为Unicode marshaller.setProperty("jaxb.encoding", "Unicode");

+1

我试图在编组期间转义字符“0x1a”转换为字符引用“$#x1a ;”并将编码更改为“Unicode”,但解编过程中仍出现错误:_Character参考“&#x1A”是无效的XML字符._ – oliverwood 2011-05-03 10:21:10

2

Unicode字符U + 001A是illegal in XML 1.0

用来表示它不会在这种情况下,重要的编码,它只是不允许出现在XML内容。

XML 1.1 allows some of the restricted characters(包括U + 001A)被包括在内,但它们必须存在作为数字字符引用(&#x1a;

维基百科有a nice summary of the situation

+0

您知道如何将Marshaller属性设置为具有XML 1.1标头吗?我试过这个,但它不起作用:'m.setProperty(“com.sun.xml.bind.xmlHeaders”,“<?xml version = \”1.1 \“?>”);' – oliverwood 2011-04-28 08:20:22

+1

它看起来像JAXB doesn目前还不支持XML 1.1:http://java.net/jira/browse/JAXB-422 – 2011-04-28 08:23:23

+1

我不认为冒犯角色是0x02,请注意{2}和{1}周围的花括号,这看起来更多像错误消息中的占位符没有被替换。 – 2011-04-28 09:10:11