XMLStreamReader没有读取完整标记

时间:2015-04-07 18:26:59

标签: java xml

我正在使用XMLStreamReader解析XML。在<dbresponse>标记中,有一些数据从数据库(WebRowSet对象)加载。问题是这个标签的内容很长(假设有几百千字节 - 数据是用Base64编码的),但是input.getText()只能读取16.394个字符。

我100%确定XMLStreamReader的数据是否正常。

我在这里找到了一些其他的答案,但它并没有解决我的问题,我当然可以使用其他方式如何读取数据,但我想知道这个问题是什么。

有人知道如何获得全部内容吗?

我的代码:

            input = xmlFactory.createXMLStreamReader(new ByteArrayInputStream(xmlData.getBytes("UTF-8")));

        while(input.hasNext()){
            if(input.getEventType() == XMLStreamConstants.START_ELEMENT){
                element = input.getName().getLocalPart();

                switch(element.toLowerCase()){
                    case "transactionresponse":
                        int transactionStatus = 0;

                        transactionResponse = new TransactionResponse(); 
                        for(int i=0; i<input.getAttributeCount(); i++){
                            switch(input.getAttributeLocalName(i)){
                                case "status": transactionStatus = TransactionResponse.getStatusFromName(input.getAttributeValue(i));
                            }
                        }

                        transactionResponse.setStatus(transactionStatus);

                        break;
                    case "dbresponse":
                        for(int i=0; i<input.getAttributeCount(); i++){
                            switch(input.getAttributeLocalName(i)){
                                case "request_id": id = Integer.parseInt(input.getAttributeValue(i)); break;
                                case "status": status = Response.getStatusFromName(input.getAttributeValue(i));
                            }
                        }

                        break;
                }
            }else if(input.getEventType() == XMLStreamConstants.CHARACTERS){
                switch(element.toLowerCase()){
                    case "dbresponse": 
                        String data = input.getText();

                        if(!data.equals("\n")){
                            data = new String(Base64.decode(data), "UTF-8");
                        }

                        Response response = new Response(data, status, id);

                        if(transactionResponse != null){
                            transactionResponse.addResponse(response);
                        }else{
                            this.addResponse(response);
                        }

                        id = -1;
                        status = -1;

                        break;
                }

                element = "";
            }else if(input.getEventType() == XMLStreamConstants.END_ELEMENT){
                switch(input.getLocalName().toLowerCase()){
                    case "transactionresponse": this.addTransactionResponse(transactionResponse); transactionResponse = null; break;
                }
            }

            input.next();

2 个答案:

答案 0 :(得分:1)

事件驱动的XML解析器(如XMLStreamReader)旨在允许您解析XML而无需一次性将其读入内存,这在您拥有非常大的XML时非常重要。< / p>

设计是这样的,它可以读取某个数据缓冲区,并为您提供事件,因为它会遇到“有趣”的内容,例如标记的开头,标记的结尾等等。

但它读取的缓冲区并不是无限的,因为它意味着处理大型XML文件,就像你拥有的那样。因此,标记中的大型文字可以由连续几次CHARACTERS个事件表示。

也就是说,当您收到CHARACTERS事件时,无法保证它包含整个文本。如果文本对于读者的缓冲区而言太长,您只会获得更多CHARACTERS个事件。

由于您只是从第一个CHARACTERS事件中读取数据,因此不是整个数据。

使用此类文件的正确方法是:

  • 当您收到感兴趣的元素的START_ELEMENT事件时,您将为存储文本做好准备。例如,创建一个StringBuilder,或打开一个文件进行写作等。
  • 对于后面的每个CHARACTERS事件,您都会将文本附加到存储空间(StringBuilder,即文件)。
  • 获得相同元素的END_ELEMENT事件后,您将完成数据的累积,并执行您需要执行的任何操作。

事实上,这就是getElementText() method为您所做的事情 - 在StringBuffer事件中累积数据,直到它遇到CHARACTERS

结论:您只知道在点击END_ELEMENT事件时获得了整个数据。无法保证文本将在单个END_ELEMENT事件中。

答案 1 :(得分:0)

我认为XMLStreamReader会对数据进行分块,所以也许尝试循环getText()来连接所有块?

getElementText()方法怎么样?