使用 SAX 解析混合内容 XML

Parsing Mixed-Content XML with SAX

我有一个示例混合内容 XML 文档(结构无法修改):

<items>
    <item>  ABC123    <status>UPDATE</status>
    <units>
        <unit Description="Each     ">EA     <saleprice>2.99</saleprice>
            <saleprice2/>
        </unit>
    </units>
    <warehouses>
        <warehouse>100<availability>2987.000</availability>
        </warehouse>
    </warehouses>
    </item>
</items>

我正在尝试在此 XML 文档上使用 SAX 解析器,但混合内容元素导致了一些问题。即,我在尝试处理 <item/> 节点时返回一个空字符串。

我的经纪人:

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

    final String fixedQName = qName.toLowerCase();
    switch (fixedQName) {
        case "item":
            prod = new Product();
            //prod.setItem(content); <-- doesn't work, content is empty since element just started
            break;
    }

}

@Override
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
    final String fixedQName = qName.toLowerCase();
    switch (fixedQName) {
        case "item":
            prod.setItem(content); // <-- doesn't work either, only returns an empty string
            // end element, set item
            productList.add(prod);
            break;
        case "status":
            prod.setStatus(content);
            break;
        // ... etc....
    }

}

@Override
public void characters(final char[] ch, final int start, final int length) throws SAXException {
    content = "";
    content = String.copyValueOf(ch, start, length).trim();
}

此处理程序对除 <item/> 元素之外的所有感兴趣的内容都能正常工作。它总是 returns 一个空字符串。

如果我将 println() 添加到 characters() 方法以打印出 content,我可以看到解析器最终确实打印了 <item/> 的内容,但是它在预期之后(在解析器的下一个附加 characters() 方法调用中)

引用 http://docs.oracle.com/javase/tutorial/jaxp/sax/parsing.html,我知道我应该尝试聚合从 characters() 返回的字符串,但是我不知道这是怎么回事,因为我确实需要检索其他元素的数据,并将第一个元素的异常硬编码到 characters() 方法中似乎是错误的方法。

如何使用 SAX 检索混合内容 <item/> 的数据 'ABC123'?

如果项目内容仅由 status 元素开始标记之前的文本组成,那么您可以在 startElement:

中获取项目内容
public void startElement(final String uri, 
    final String localName, final String qName, final Attributes attributes) throws SAXException {

    final String fixedQName = qName.toLowerCase();
    switch (fixedQName) {
         case "item":
             prod = new Product();
             break;
         case "status":
             prod.setItem(content);
             break;
    }
}

要理解事件流:

  • 开始元素item
  • 个字符"ABC123"
  • 开始元素status
  • 个字符"UPDATE"
  • endElement status
  • 个字符""
  • endElement item