1

STAX イベント API を使用して、SOAP 呼び出しから受信したバイナリ データを読み取り、それをコンシューマーにストリーミングしたいと考えています。SOAP 呼び出しからの XML ペイロードは次のようになります。

    .........
    <BinaryObject mimeCode="text/xml">PHNvYXAtZW52OkVudmVsb3BlIHhtbG5zOnNvYXAtZW52PSJodHRwOi8vc
         2NoZW1hcy54bWxzb2FwLhm9yZy9zb2FwL2VudmVsb3BlLyI+DQogICA8c29hcC1lbnY6SGVhZGVy
         Lz4NCiAgIDxzb2FwLWVudjpCb2R5Pg0KICAgICAgPG5tOkF0dGFjaG1lbnRGb2xkZXJEb2N1bWVudE
         ZpbGVDb250ZW50QnlJRFJlc3BvbnNlX3N5bmMgeG1sbnM6bm09Imh0dHA6Ly9zYXAuY29tL3hpL1NB
         UEdsb2JhbDIwL0dsb2JhbCIgeG1sbnM6cHJ4PSJ1cm46c2FwLmNvbTpwcm94eTpISlc6LzFTQUkvVE
         FTMEIzNDE4MTJBNTc5MDUyM0I5RTU6ODA0Ij4NCiAgICAgICAgIDxBdHRhY..... </BinaryObject>

以下は、データを解析して消費者に送信するために使用する Java コードです。

    XMLInputFactory inputFactory = XMLInputFactory.newInstance();
    inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);

    InputStream in;

    try {

        in = new ByteArrayInputStream(response.getBytes());

        XMLEventReader eventReader;
        eventReader = inputFactory.createXMLEventReader(in);

        while (eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();

            // Start element
            if (event.isStartElement()) {
                StartElement startElement = event.asStartElement();

                if (startElement.getName().getLocalPart().toString()
                        .equals("BinaryObject")) {

                    Iterator<Attribute> attributes = startElement
                            .getAttributes();

                    while (attributes.hasNext()) {
                        Attribute attribute = attributes.next();

                        if (attribute.getName().toString()
                                .equals("mimeCode")) {
                            mimeType = attribute.getValue();
                        }
                    }

                    event = eventReader.peek();

                    if (event.isCharacters()) {
                        event = eventReader.nextEvent();
                        content = event.asCharacters().getData();
                    }
                }
            }
        }

    } catch (XMLStreamException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    m_servletResponse.setContentType(mimeType);
        m_servletResponse.getWriter().print(javax.xml.bind.DatatypeConverter
                .printBase64Binary(content.getBytes()));

このコードには複数の問題があります。

  1. 大きなファイル (> 1 MB) の場合、StackOverflow エラーが発生します

  2. 小さいファイルでも、png ファイルを試してみると、ファイルが無効であるというエラーが表示されます (消費者側で)。

これらの問題をどのように克服できますか?

PS: STAXは初めてです!!

==================== 編集: ====================**

以下の Evgeniy からの提案に基づいて、小さなファイル (PNG など) を処理できるようになりました。ただし、1 MB を超える大きな PDF ドキュメントの場合、以下のエラーが発生します。ここで何がうまくいかないのかについてのアイデアはありますか?

2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null#例外「http-bio- 8041-exec-9" | 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null#java.lang.StackOverflowError| 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# at com.sun.org.apache .xerces.internal.impl.XMLScanner.isInvalid(XMLScanner.java:1334)| 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# at com.sun.org.apache .xerces.internal.impl.XMLScanner.scanCharReferenceValue(XMLScanner.java:1294)| 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# at com.sun.org.apache .xerces. internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3024)| 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# at com.sun.org.apache .xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2919)| 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# at com.sun.org.apache .xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3059)| sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2919)| 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# at com.sun.org.apache .xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3059)| sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2919)| 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# at com.sun.org.apache .xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3059)|

4

1 に答える 1

1

まず第一に、XMLEventReader特別な目的のために設計されており、XMLStreamReader代わりに使用してください。これが実際の例です

        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
        InputStream in = new ByteArrayInputStream(response.getBytes());
        XMLStreamReader xr = inputFactory.createXMLStreamReader(in);
        while (xr.hasNext()) {
            int next = xr.next();
            if (next == XMLStreamConstants.START_ELEMENT) {
                if (xr.getLocalName().equals("BinaryObject")) {
                    String mimeCode = xr.getAttributeValue(null, "mimeCode");
                    if (mimeCode.equals("text/xml")) {
                        xr.next();
                    // for efficiency we can access xr inner buffer chars directly
                    char[] b = xr.getTextCharacters();
                    int textStart = xr.getTextStart();
                    int textLength = xr.getTextLength();
                    // or simply get it as String  
                    String text = xr.getText();
                    // in this example I will use JDK's internal decoder com.sun.org.apache.xerces.internal.impl.dv.util.Base64                     
                    byte[] bytes = new Base64().decode(text);

                    }
                }
            }
        }
于 2012-12-08T07:30:18.957 に答える