【问题标题】:How to parse mulitple XML files in Java with XMLStreamReader如何使用 XMLStreamReader 解析 Java 中的多个 XML 文件
【发布时间】:2018-07-01 07:50:47
【问题描述】:

我们必须从为一堆气象站创建假天气数据的生成器中解析 xml 信息。目前我们只是打印它,但我们稍后将不得不对其进行处理。 但是,我们收到的数据由多个 XML“文件”组成。有没有办法分离数据并将其拆分为新的<?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 文件,但我不确定这是否有用。

【问题讨论】:

  • 请不要在代码中使用脏话。不专业,不适合本站。
  • 我的错。删除它。
  • 您是在问如何解析同一个文件或不同文件中的多个 MEASUREMENT 元素?这个问题有点混乱。
  • 我们从与连续流相同的来源接收多个 &lt;?xml...?&gt;&lt;MEASUREMENT&gt;&lt;/MEASUREMENT&gt; 文件(我猜它们不是文件,但我不确定还能如何称呼它)。
  • 您可以尝试实现FilterInputStream 并删除(后续?)&lt;?xml version="1.0"?&gt; 条目,如果这是给您带来麻烦的原因。

标签: java xml serversocket xmlstreamreader


【解决方案1】:

使用java.util.Scanner 可以作为一种快速解决方法。 disassemble() 函数会跳过 XML 声明(如果存在),并将直到并包括下一个结束 &lt;/WEATHERDATA&gt; 标记的所有字符组合成一个“字符串”。然后将结果传递给回调,在此示例中,回调将 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 + '\'' + '}'; }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-23
    • 2012-03-26
    • 1970-01-01
    • 2015-09-11
    • 2017-07-27
    • 2021-12-09
    • 1970-01-01
    • 2013-02-06
    相关资源
    最近更新 更多