【问题标题】:Deserializing xml with XMLScanner causing the output string to be bigger使用 XMLScanner 反序列化 xml 导致输出字符串更大
【发布时间】:2014-07-07 08:17:30
【问题描述】:

我们的产品升级过程包括将旧模式数据库导出到文件(JAXB 序列化),然后导入到新模式(StAX + JAXB)。有时升级会由于插入错误而失败,这些错误是由超出其最大大小的值引起的,尽管它们以前是从同一个数据库表中导出的。

这发生在反序列化 xml(在这种情况下使用 Jaxb,但它与 Jaxb 无关)并且其中一个属性具有高代理 UTF-8 字符序列的值时,SAX 解析器存在导致输出字符串更大的错误:

3 个字符 -> (1+2+3=) 6 个字符。
6 个字符 -> (1+2+3+4+5+6=) 21 个字符。
(源字符的算术级数)

代码来自 java 1.7_45 代码类 com.sun.org.apache.xerces.internal.impl.XMLScanner 行:976 - 981:

else if (c != -1 && XMLChar.isHighSurrogate(c)) {
    if (scanSurrogates(fStringBuffer3)) {
        stringBuffer.append(fStringBuffer3);
    if (entityDepth == fEntityDepth && fNeedNonNormalizedValue){
        fStringBuffer2.append(fStringBuffer3); 
    } 

fStringBuffer3 在循环之间没有清除缓冲区。

com.sun.org.apache.xerces.internal.impl.XML11DocumentScannerImpl 行中存在类似的代码(相同的方法名称):369 - 375。但是这次在循环期间清除了缓冲区:

else if (c != -1 && XMLChar.isHighSurrogate(c)) {
        fStringBuffer3.clear();
        if (scanSurrogates(fStringBuffer3)) {
            fStringBuffer.append(fStringBuffer3);
        if (entityDepth == fEntityDepth) {
            fStringBuffer2.append(fStringBuffer3);
        }
   }

我检查了 java bug 数据库,那里没有提到这个 bug。 所以我正在寻找解决这个问题的方法,用 Woodstox 解析器替换 JAXB 解析器解决了这个错误, 不幸的是,现在对我们来说风险太大了。

我的代码的一般模式是(返回从文件反序列化的对象的方法的一部分):

XMLInputFactory xmlif = XMLInputFactory.newInstance();
XMLStreamReader xmlStreamReader = xmlif.createXMLStreamReader(new FileReader(file)); 
try {
    while(xmlStreamReader.hasNext()){
        boolean skipNext = xmlStreamReader.getEventType() == XMLStreamConstants.START_DOCUMENT;
        xmlStreamReader.next();
        // If its any other element we are unmarshalling it with JAXB
        if((xmlStreamReader.getEventType()== XMLStreamConstants.START_ELEMENT) && !skipNext){
            nextElement = innerDeserializer.deserialize();
        }
    }
}catch (Exception e) {}

有人遇到过这个问题吗?有什么方法可以让我的代码使用第二段代码而不使用 XML 1.1 版?

【问题讨论】:

    标签: java xml jaxb stax woodstox


    【解决方案1】:

    如果错误出现在默认情况下 JAXB 参考实现用于 XML 处理的 SAX 解析器中。您可以在输入上创建一个 StAX XMLStreamReader 并让 JAXB 解组它。

    【讨论】:

    • 这就是我们正在做的,使用 StAX 读取大型文档块,而每个 START_ELEMENT 事件都使用 JAXB 解析。
    • @MaximKirilov - 我很困惑 SAX 解析器的来源。
    • 感谢您的帮助,我编辑了上面的代码并添加了我的代码的一般模式,显示了 StAX 与 JAXB 的组合。
    • @MaximKirilov - 所以 StAX 方法有效,你只是认为它有风险,你为什么认为它有风险?除了 Woodstox 之外,JDK/JRE 中还有一个 StAX 解析器,它对你有用吗?
    猜你喜欢
    • 1970-01-01
    • 2021-06-07
    • 2013-01-16
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 2012-11-07
    相关资源
    最近更新 更多