当文档中某处存在异常大的值时,SAX 解析器读取 XML 元素的部分

SAX parser reading portion of XML element when there is unusually big value somewhere in the document

我使用 SAX 解析器从大型 XML 文件中读取一些元素。下面是示例 XML 和我为此目的使用的 SAX 解析器代码。

<someOtherElement>231</someOtherElement>
<someMoreOtherElement>1233.00213</someMoreOtherElement>
...
<elementToRead1>31.0.1</elementToRead1>
<elementToRead2>ABCD-XYZ-1.0</elementToRead2>

解析器代码:

public class MyHandler extends DefaultHandler {

    private String elementToRead1

    private Boolean flag1 = false;

    private String elementToRead2

    private Boolean flag2 = false;

    public void readValues(final String xmlString) throws XMLParseException {
        SAXXMLParser.parseString(xmlString, this);
    }

    @Override
    public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) {

        if (""elementToRead1"".equals(qName)) {
            flag1 = true;
        }

        if (""elementToRead2"".equals(qName)) {
            flag2 = true;
        }
    }

    @Override
    public void characters(final char ch[], final int start, final int length) {
        if (flag1) {
            elementToRead1 = new String(ch.clone(), start, length);
            flag1 = false;
        }

        if (flag2) {
            elementToRead2 = new String(ch.clone(), start, length);
            flag2 = false;
        }
    }

}

一切正常,我正在使用此代码获得正确的值。但是在测试时,我尝试将 XML 中的一个元素的值更改为非常长的值,因此,我需要在解析器中读取的元素之一开始错误地选择它。 假设问题XML是:

 <someOtherElement>231</someOtherElement>
<someMoreOtherElement>9999999999999999999999999999999999999999999999999999999999999991233.00213</someMoreOtherElement>
...
<elementToRead1>31.0.1</elementToRead1>
<elementToRead1>ABCD-XYZ-1.0</elementToRead2>

对于这种XML,元素的值总是这样读取:

elementToRead1 - 31.0.1

elementToRead2 - ABCD-XYZ-1

我不知道为什么第二个元素读错了。我已经尝试使用调试点和所有东西,我可以确认没有任何地方抛出异常。在这个问题的情况下,只有第二个元素的值被读取错误 XML.

我有一个类似的问题,它是由为值调用不止一次的字符方法引起的。您需要使用 StringBuilder 并附加字符以获得正确的值,然后在 endElement 中设置值并重置构建器。

应该可以。

@Override
public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) {
    stringBuffer.setLength(0);

    if ("elementToRead1".equals(qName)) {
        flag1 = true;
    }
}

@Override
public void characters(char ch[], int start, int length) {
    stringBuffer.append(new String(ch, start, length));
}

@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
    String result = stringBuffer.toString();

    if (flag1) {
        elementToRead1 = result;
        flag1 = false;
    }
}

来自docs

SAX parsers may return all contiguous character data in a single chunk, or they may split it into several chunks; however, all of the characters in any single event must come from the same external entity so that the Locator provides useful information.