如何使用XMLStreamReader

时间:2018-01-22 16:02:58

标签: java xml serversocket xmlstreamreader

我们必须解析来自生成器的xml信息,该生成器为一堆天气预报器创建假天气数据。目前我们只是打印它,但我们以后必须用它来做。 但是,我们收到的数据包含多个XML&#34;文件&#34;。有没有办法分离数据并将其拆分为新的<?xml...?>? (数据是随机分割的连续流) 我们的代码:

public class Main {

static private final int portNumber = Null;

public static void main(String[] args) {
    try {
        ServerSocket serverSocket = new ServerSocket(portNumber);
        Socket clientSocket = serverSocket.accept();

        BufferedReader clientReader = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));


        XMLInputFactory factory = XMLInputFactory.newInstance();
        XMLStreamReader reader = factory.createXMLStreamReader(clientReader);

        while (reader.hasNext()) {
            int event = reader.next();

            if (event == XMLStreamConstants.START_ELEMENT) {
                try {
                    String text = reader.getElementText();
                    System.out.println("Element Local Name:" + reader.getLocalName());
                    System.out.println("Text:" + text);

                } catch (XMLStreamException e) {
                    System.out.println(e);
                }
            }
            else if(event == XMLStreamConstants.END_ELEMENT){
                reader.close();
            }

        }
    } catch (IOException e) {
        System.out.println("Error: Unable to Start Server Socket\n\t" + e);
    } catch (XMLStreamException e){
        System.out.println(e);

    }
}
}

xml的例子(我们彼此接收多个):

<?xml version="1.0"?>
<!-- The WEATHERDATA-element contains multiple MEASUREMENT-elements -->
<WEATHERDATA>
    <MEASUREMENT>
        <STN>123456</STN>

        <DATE>2009-09-13</DATE>

        <TIME>15:59:46</TIME>

        <TEMP>-60.1</TEMP>

        <DEWP>-58.1</DEWP>

        <STP>1034.5</STP>

        <SLP>1007.6</SLP>

        <VISIB>123.7</VISIB>

        <WDSP>10.8</WDSP>

        <PRCP>11.28</PRCP>

        <SNDP>11.1</SNDP>

        <FRSHTT>010101</FRSHTT>

        <CLDC>87.4</CLDC>

        <WNDDIR>342</WNDDIR>
    </MEASUREMENT>
</WEATHERDATA>

我们也有dtd文件,但我不确定这是否有用。

1 个答案:

答案 0 :(得分:0)

使用java.util.Scanner可以作为快速解决方法。 disassemble()函数跳过XML声明(如果存在),并将所有字符组合到下一个结束</WEATHERDATA>标记并包含在`String'中。然后将结果传递给回调,在此示例中,回调将XML转换为带有JAXB的POJO。

我不喜欢Scanner,它在内部缓冲输入流,因此当流关闭时可能会丢失最后一条消息。

public class DisassembleXml {
    private static final int port = 8888;
    private static final Pattern XML_DECL_PATTERN = Pattern.compile("<\\?xml.*?\\?>");
    private static final Pattern DATA_PATTERN = 
        Pattern.compile(".*?</WEATHERDATA>\\s+", Pattern.DOTALL);

    public static void main(String[] args) throws Exception {
        final ServerSocket serverSocket = new ServerSocket(port);
        System.out.printf("Listening on %d%n", serverSocket.getLocalPort());
        final Socket clientSocket = serverSocket.accept();
        System.out.printf("Processing from %s%n", clientSocket);

        try (Reader sr = new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.ISO_8859_1))
        {
            disassemble(sr, new ConvertToPojoAndPrint());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private static void disassemble(Reader reader, Consumer<String> xmlConsumer) {
        final Scanner sc = new Scanner(reader).useDelimiter("\\Z");
        try {
            while (true) {
                final String xml = sc
                    .skip(XML_DECL_PATTERN)
                    .findWithinHorizon(DATA_PATTERN, 0);
                if (xml == null || xml.isEmpty())
                    break;
                xmlConsumer.accept(xml);
            }
        }
        catch (Exception e) {
            throw new IllegalStateException("cannot interpret stream", e);
        }
    }

    private static class ConvertToPojoAndPrint implements Consumer<String>
    {
        final JAXBContext jaxbContext;
        final Unmarshaller unmarshaller;

        ConvertToPojoAndPrint() throws JAXBException {
            jaxbContext = JAXBContext.newInstance(WeatherData.class);
            unmarshaller = jaxbContext.createUnmarshaller();
        }

        @Override
        public void accept(String xml) {
            try {
                final WeatherData weatherData = (WeatherData) unmarshaller.unmarshal(new StringReader(xml));
                System.out.println("Another sample: " + weatherData);
            }
            catch (Exception e) {
                throw new IllegalStateException(e);
            }
        }
    }

    @XmlRootElement(name = "WEATHERDATA")
    private static class WeatherData
    {
        @XmlElement(name = "MEASUREMENT")
        Measurement measurement;
        @Override
        public String toString() { return "WeatherData{" + "measurement=" + measurement + '}'; }
    }

    private static class Measurement
    {
        @XmlElement(name = "STN")
        String stn;
        // ... skipping the rest of elements for brevity
        @Override
        public String toString() { return "Measurement{" + "stn='" + stn + '\'' + '}'; }
    }
}