0

我在 Axis2 中使用 Axiom 从 SOAP 消息的大型 base64Binary 部分中提取文本。我的接收器没有使用 MTOM,而是OMElement.getTextAsStream( false )用来提取文本。代码看起来像这样:

final Iterator<OMElement> childrenIterator = uploadFile.getChildElements();
while ( childrenIterator.hasNext() )
{
    final OMElement element = childrenIterator.next();
    if ( "fileID".equals( element.getLocalName() ) )
    {
        fileID = element.getText();
    }
    // fileContent contains a large base64Binary block
    else if ( "fileContent".equals( element.getLocalName() ) )
    {
        Reader reader = element.getTextAsStream( false );

        final char[] buf = new char[BUFFER_SIZE];
        int len = 0;
        while ( (len = reader.read( buf ) ) >= 0 )
        {
            if ( len > 0 )
            {
                // Process chunk here
            }
        }
    }
}

示例 XML 看起来像

<uploadFile>
    <fileID>id</fileID>
    <fileContent>~500kB of base64 data</fileContent>
</uploadFile>

childrenIterator.hasNext()在读取 base64Binary 数据后,我在线上遇到了这个异常:

Caused by: org.apache.axiom.om.OMException: Parser has already reached end of the document. No siblings found
    at org.apache.axiom.om.impl.llom.OMElementImpl.getNextOMSibling(OMElementImpl.java:359)
    at org.apache.axiom.om.impl.traverse.OMChildrenIterator.getNextNode(OMChildrenIterator.java:36)
    at org.apache.axiom.om.impl.traverse.OMAbstractIterator.hasNext(OMAbstractIterator.java:69)
    at org.apache.axiom.om.impl.traverse.OMFilterIterator.hasNext(OMFilterIterator.java:54)

我做了一些调查,这肯定与我false在调用时设置缓存有关getTextAsStream()。我需要这样做,因为 base64 数据的潜在大小可能是数百兆字节。

问题似乎在于TextFromElementReader将底层推进XMLStreamReader到 END_ELEMENT 事件。 OMElementImpl.getNextOMSibling()然后调用next()底层证券XMLStreamReader并获取 END_DOCUMENT 事件。似乎TextFromElementReader需要遇到 END_ELEMENT 才能知道它已经到达文本段的末尾,但这会使底层代码XMLStreamReader处于错误的状态OMElementImpl.getNextOMSibling()

有没有人见过这个错误?我使用 Axiom 的方式有问题吗?

4

1 回答 1

0

我最终根本没有使用 getTextAsReader。相反,我遍历子文本节点并以这种方式分块处理文本内容。解析器被配置为非合并,所以我得到合理大小的文本节点而不是一个大的。

OMNode child = omElement.getFirstOMChild();
while ( child != null )
{
    if ( child instanceof OMText )
    {
        // process 'child' text here

        final OMNode nextSibling = child.getNextOMSibling();
        child.detach();    // detach from OM to keep memory usage low
        child = nextSibling;
    }
}
于 2013-01-22T03:15:57.303 回答