繁体   English   中英

从Stax XMLStreamReader读取以解组部分

[英]Read from Stax XMLStreamReader to unmarshall partial

我正在使用Stax光标api从大型xml文件提取数据。 当前,我转到一个特殊标签的开头,然后用JAXB解组该标签。 在格式良好的xml文件上可以正常工作。 但是不久前,我有一个文档,其中成千上万个标签中的一个没有关闭。 JAXB逐步使用XMLStreamReader,直到文档末尾失败。 有没有一种方法可以从开始标签读取到结束标签,然后将其分开编组? 因此,我将丢失带有Exception的两个标签,而不是文档的其余部分。 我发现的唯一方法是使用普通的BufferedReader而不是XMLStreamReader并检查行内容。 但是在我看来,这种解决方案很难看。

使用jackson对XML片段进行反序列化时,我已经取得了一定的成功。 当个别读取失败时,可以通过将光标前进到下一个片段来恢复该过程:

import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.StringReader;

public class XmlFragmentReader {
    public static void main(String[] args) throws XMLStreamException {
        String xml =
            "<list>\n" +
            "<object><name>a</name></object>\n" +
            "<object><name>b</name>\n" + // Missing closing tag
            "<object><name>c</name></object>\n" +
            "<object><name>d</name></object>\n" +
            "<object><name>e</name></object>\n" +
            "</list>";

        XMLStreamReader reader = XMLInputFactory
            .newInstance()
            .createXMLStreamReader(new StringReader(xml));

        XmlMapper mapper = new XmlMapper();
        while (next(reader, "object")) {
            try {
                Obj obj = mapper.readValue(reader, Obj.class);
                System.out.println("Read: " + obj.getName());
            } catch (Exception e) {
                System.err.println("Read Failed: " + e);
            }
        }
    }

    // Advance cursor to the opening tag <name>
    private static boolean next(XMLStreamReader reader, String name) throws XMLStreamException {
        while (true) {
            if (reader.getEventType() == XMLStreamConstants.START_ELEMENT && reader.getLocalName().equals(name)) {
                return true;
            } else if (!reader.hasNext()) {
                return false;
            }
            reader.next();
        }
    }

    // Test object
    @XmlRootElement(name = "object")
    public static class Obj {
        private String name;

        @XmlElement
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

输出:

Read a
Read d
Read e

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM