代码之家  ›  专栏  ›  技术社区  ›  David Sauter

XMLStreamReader问题

  •  2
  • David Sauter  · 技术社区  · 14 年前

    我用的是 XMLStreamReader 接口来自 javax.xml 解析XML文件。该文件包含大量数据和几个KB的单个文本节点。

    验证和读取通常工作得很好,但对于大于15k个字符的文本节点,我遇到了问题。此函数中出现问题

    String foo = "";
    if (xsr.getEventType() == XMLStreamConstants.CHARACTERS) {
        foo = xsr.getText();
        xsr.next(); // read next tag
    }
    return foo;
    

    xsr 成为流阅读器。在这种特殊情况下,文本节点中的文本长度为53'337个字符(但有所不同),但是 xsr.getText() 方法只返回其中的前15'537。当然,我可以在函数上循环并连接字符串,但不知何故,我不认为这是个主意。。。

    我没有在文件或其他任何地方找到任何关于这个。这是有意的行为还是有人可以确认/否认?我用错了吗?

    谢谢

    2 回复  |  直到 14 年前
        1
  •  1
  •   skaffman    14 年前

    当然,我可以在函数上循环并连接字符串,但不知何故,我不认为这是个主意。。。

    实际上,那 想法:)

    只要事件流与原始文档一致,解析器就可以按照自己的意愿分解事件流。这意味着它可以,而且通常会,将文本数据分解成多个事件。如何以及何时选择这样做是解析器内部的一个实现细节,本质上是不可预测的。

    所以是的,如果你收到多个 CHARACTERS 事件,需要手动附加它们。这是你为一个低级API所付出的代价。

        2
  •  0
  •   yonran    13 年前

    另一个选择是 javax.xml.stream.isCoalescing 选项(记录在 XMLStreamReader.next() Using StAX ),它自动将长文本连接到单个字符串中。下面的JUint3测试通过了。

    警告 :isCoalescing可能不应在生产环境中使用,因为如果文档具有大量字符引用(   )或实体引用( < ),它将导致stackoverflower错误!

    import java.io.ByteArrayInputStream;
    import java.io.InputStream;
    
    import javax.xml.stream.XMLInputFactory;
    import javax.xml.stream.XMLStreamException;
    import javax.xml.stream.XMLStreamReader;
    
    import junit.framework.TestCase;
    
    public class XmlStreamTest extends TestCase {
        public void testLengthInXMlStreamReader() throws XMLStreamException {
            StringBuilder b = new StringBuilder();
            b.append("<root>");
            for (int i = 0; i < 65536; i++)
                b.append("hello\n");
            b.append("</root>");
            InputStream is = new ByteArrayInputStream(b.toString().getBytes());
            XMLInputFactory inputFactory = XMLInputFactory.newFactory();
            inputFactory.setProperty("javax.xml.stream.isCoalescing", true);
            XMLStreamReader reader = inputFactory.createXMLStreamReader(is);
            reader.nextTag();
            reader.next();
            assertEquals(6 * 65536, reader.getTextLength());
        }
    }