如何使用Android上的DocumentBuilder DOM解析器解析包含非拉丁Unicode字符的标记名称的XML

时间:2015-10-30 20:10:11

标签: android xml dom unicode

好的,我有一个由其他人编写的Android应用程序但是我的工作是维护和进一步开发。该应用程序使用以XML格式回答的API。代码很标准:

InputStream in = httpConnection.getInputStream();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom = db.parse(in);

除非标签名称中包含非拉丁字符,否则一切正常。 例如,这没关系:

<Milen>some_text</Milen>

但这引起了例外:

<Милен>some_text</Милен>

例外是INVALID_CHARACTER_ERR。经过一些调查,我发现DOM API的实施是org.apache.harmony.xml.dom.DocumentImpl。并且在第286行引发了异常here。如果检查归结为此方法:

private static boolean isXMLIdentifierPart(char c) {
    return isXMLIdentifierStart(c) || (c >= '0' && c <= '9') || (c == '-') || (c == '.');
}

这基本上排除了任何非拉丁字符。 Howerver,根据this任何Unicode字符都是有效的标记名称。

所以我的问题是:

  1. 为什么会出现违反标准的检查?
  2. 有什么选择让DOM解析器与非拉丁语Unicode字符一起使用?
  3. 一些补充说明:

    • 服务器返回正确的UTF-8响应
    • 我尝试过使用XML escaping但显然在签入isXMLIdentifierPart之前会将其转换回原始的Unicode
    • 我非常喜欢坚持使用DOM解析器API,因为之后的处理会假定将Document对象传递给它。重写处理将是很多工作。

    我正在考虑的两个解决方案是:

    1. 获取org.apache.harmony.xml.dom.DocumentImpl实现的代码并创建缺少有问题检查的自定义解析器。
    2. 让服务器使用一些使用仅拉丁字符(\ u1234或U + 1234不起作用)的自定义架构对非拉丁字符进行编码,然后在解析器完成后对其进行解码。
    3. 然而,这两种解决方案都是非标准的,并且不喜欢它们。因此,任何正确的方法都非常受欢迎!!!

      免责声明:我是Android平台的新手,我可能会遗漏一些简单/明显的东西。然而,经过两天的研究和实验,我还没有找到它。

1 个答案:

答案 0 :(得分:2)

  

根据此,任何Unicode字符都是有效的标记名称。

不完全任何字符,但是,在第五版中,允许绝大多数非ASCII字符(在此之前规则相当复杂,但仍然允许很多)。

  

为什么会出现违反标准的检查?

因为Harmony DOM实现是一个错误的,不符合要求,维护不善的堆,不能正确地实现旧规范,因此只能禁止非ASCII。在其他许多问题中。

这是issue 78387 FWIW。

  

我有什么选择让DOM解析器与非拉丁语Unicode字符一起使用?

看看你是否能找到一个替代的,破坏性较小的DOM实现。

  

获取org.apache.harmony.xml.dom.DocumentImpl实现的代码并创建一个缺少有问题检查的自定义解析器。

(是的,这可能必须是一个合适的分支,因为单独进行子类化很难。太多的类都有明确的引用。)