【问题标题】:How to add XML elements from List into XMLEventWriter? Append XML to already created XMLEventWriter/XmlStreamWriter如何将列表中的 XML 元素添加到 XMLEventWriter 中?将 XML 附加到已创建的 XMLEventWriter/XmlStreamWriter
【发布时间】:2021-08-30 15:33:52
【问题描述】:

我有一个List<String>,其中包含作为JAXB Marshaling 方法输出的一部分创建的XML 事件。在完成JAXB Marshaling 进程后,这个List<String> 可以包含大量的XML。

这些XML 片段是大型XML 的一部分。大型 XML 有一些额外的标头元素,因此我尝试使用 XMLEventWriter 创建 large XML 并尝试从我的 LIST<String> 添加元素,但它无法按预期工作并遇到各种错误。

我收到以下错误:

Exception in thread "main" javax.xml.stream.XMLStreamException: Trying to output second root

以下是我的代码:

import javax.xml.namespace.QName;
import javax.xml.stream.*;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

public class TestMain {
    public static void main(String[] args) throws XMLStreamException {
        final XMLEventWriter xmlEventWriter = XMLOutputFactory.newInstance().createXMLEventWriter(System.out);
        final XMLEventFactory events = XMLEventFactory.newInstance();
        List<String> eventList = new ArrayList<>();
        eventList.add("<fragment><data>First Event</data></fragment>");
        eventList.add("<fragment><data>Second Event</data></fragment>");
        eventList.add("<another><data>Third Event</data></another>");

        xmlEventWriter.add(events.createStartDocument());
        xmlEventWriter.add(events.createStartElement(new QName("root"), null, null));
        xmlEventWriter.add(events.createStartElement(new QName("fragments"), null, null));
        for (String event : eventList) {
            final XMLEventReader xer = XMLInputFactory.newInstance().createXMLEventReader(new StringReader(event));
            if (xer.peek().isStartDocument()) {
                xer.nextEvent();
                xmlEventWriter.add(xer);
            }
        }
        xmlEventWriter.add(events.createEndDocument());
        xmlEventWriter.add(events.createEndDocument());
        xmlEventWriter.close();


    }
}

以下是我期待的输出:

<root>
    <fragments>
        <fragment>
            <data>First Event</data>
        </fragment>
        <fragment>
            <data>Second Event</data>
        </fragment>
        <another>
            <data>Third Event</data>
        </another>
    </fragments>
</root>

我查看了XMLStreamWriter,但我知道使用它无法做到这一点。我对XMLEventWriter 并不特别。我只想使用任何方法/库获得所需的输出。

有人可以帮我解决这个问题吗?我只想将List 中的XML 添加到已经用几个节点创建的XMLEventWriter

【问题讨论】:

  • 我不知道你为什么认为你需要(或想要)使用 XMLEventWriter(或 -Reader); XMLStreamWriter 和 XMLStreamReader 在这里应该可以正常工作,并且开销也较低。方法@andreas 大纲应该有效。如果您需要缓冲事件以进行存储或转换,则事件方法最有用;但对于即时生成/翻译而言,价值不大。

标签: java xml stax woodstox xmlstreamwriter


【解决方案1】:

首先,你的结局事件是错误的:

xmlEventWriter.add(events.createEndDocument());
xmlEventWriter.add(events.createEndDocument());

他们应该是:

xmlEventWriter.add(events.createEndElement(new QName("fragments"), null));
xmlEventWriter.add(events.createEndElement(new QName("root"), null));
xmlEventWriter.add(events.createEndDocument());

其次,问题是xer 事件阅读器以您不想复制的“结束文档”事件结束,因此您需要将其过滤掉。

为此,将xer 包装在一个委托中,该委托在到达“结束文档”事件时结束事件流:

xer = new EventReaderDelegate(xer) {
    @Override
    public boolean hasNext() {
        if (! super.hasNext())
            return false;
        try {
            return ! super.peek().isEndDocument();
        } catch (@SuppressWarnings("unused") XMLStreamException ignored) {
            return true;
        }
    }
};

【讨论】:

  • 非常感谢您的快速回复。确实奏效了。从下午开始,我一直在尝试纠正它,但没有任何进展。只是出于好奇,您是否有某种文档是在哪里找到的?还是你的知识?我只是想知道在哪里可以找到这样的东西。再次非常感谢,您应该得到赞成和接受的答案。祝你有美好的一天:)
  • 另外,还有一个问题。我正在使用XMLEventWriter 创建一个大型 XML。 List&lt;String&gt; eventList 可以包含 1000 个条目这是最好的选择还是有比这更好的东西可以使用?我以前使用XMLStreamWriter,但后来我发现我不能用它做类似的事情,所以我切换到XMLEventWriter。只是想确认这是否是处理大型 XML 的最有效和最有效的方法。
  • @BATMAN_2008 我刚刚查看了XMLEventReader 的javadoc,发现EventReaderDelegate 被列为已知的实现类。然后我创建了一个测试程序(你的代码的副本),包装了xer 并使用打印语句实现了一些方法,所以我可以看到它是如何使用的。仅调用了hasNext()nextEvent(),因此很容易发现只需调整hasNext() 即可防止返回EndDocument 事件。
  • @BATMAN_2008 使用XMLEventWriter 很好。但是eventList 是从哪里来的。您提到字符串是 JAXB 编组的结果,Marshaller 可以将marshal 直接转换为XMLEventWriter,因此可以跳过整个中间 XML 字符串。另一种选择,编组为字符串,但随后立即执行xer,而不是建立一个列表。
  • @BATMAN_2008 我已经告诉过你更好的方法:边写边写。编组第一个 XML,对其进行验证,然后将其写入最终的 XML 流。对下一个 XML 重复此操作。没有列表建立 = 减少内存使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-30
  • 2021-04-30
  • 1970-01-01
  • 2013-08-16
  • 2016-08-27
  • 2015-09-15
  • 2019-10-14
相关资源
最近更新 更多