【问题标题】:Update XML using XMLStreamWriter使用 XMLStreamWriter 更新 XML
【发布时间】:2013-09-02 11:44:48
【问题描述】:

我有一个很大的 XML,我想更新 XML 的特定节点(例如删除重复节点)。

由于 XML 很大,我考虑使用 STAX api 类 - XMLStreamReader。我首先使用 XMLStreamReader 读取 XML。我将读取的数据存储在用户对象中并操作这些用户对象以删除重复项。

现在我想把这个更新的用户对象放回到我原来的 XML 中。我的想法是我可以将用户对象编组为一个字符串,并将该字符串放在我的输入 xml 中的正确位置。但我无法使用 STAX 类来实现它 - XMLStreamWriter

这可以使用 XMLStreamWriter 实现吗?请建议。 如果不是,请他们为我的问题提出一种替代方法。

我主要关心的是内存,因为我无法将如此庞大的 XML 加载到我们的项目服务器的内存中,该内存在多个进程之间共享。因此我不想使用 DOM,因为这将使用大量内存来加载这些巨大的 XML。

【问题讨论】:

  • 另外,请注意,在用户对象(bean)中,我只加载了需要修改的部分。我没有将整个 XML 加载到 bean 中只是为了节省内存。

标签: java xml stax xmlstreamreader


【解决方案1】:

如果您需要更改特定值,例如文本内容/标签名称等,STAX 可能会有所帮助。它还有助于使用createFilteredReader删除一些元素

以下代码将Name重命名为AuthorName并添加注释

public class StAx {
    public static void main(String[] args) throws FileNotFoundException,
            XMLStreamException {

        String filename = "HelloWorld.xml";

        try (InputStream in = new FileInputStream(filename);
                OutputStream out = System.out;) {
            XMLInputFactory factory = XMLInputFactory.newInstance();
            XMLOutputFactory xof = XMLOutputFactory.newInstance();
            XMLEventFactory ef = XMLEventFactory.newInstance();

            XMLEventReader reader = factory.createXMLEventReader(filename, in);
            XMLEventWriter writer = xof.createXMLEventWriter(out);

            while (reader.hasNext()) {
                XMLEvent event = (XMLEvent) reader.next();
                if (event.isCharacters()) {
                    String data = event.asCharacters().getData();
                    if (data.contains("Hello")) {
                        String replace = data.replace("Hello", "Oh");
                        event = ef.createCharacters(replace);
                    }
                    writer.add(event);
                } else if (event.isStartElement()) {
                    StartElement s = event.asStartElement();
                    String tagName = s.getName().getLocalPart();
                    if (tagName.equals("Name")) {
                        String newName = "Author" + tagName;
                        event = ef.createStartElement(new QName(newName), null,
                                null);
                        writer.add(event);
                        writer.add(ef.createCharacters("\n          "));
                        event = ef.createComment("auto generated comment");
                        writer.add(event);
                    } else {
                        writer.add(event);
                    }
                } else {
                    writer.add(event);
                }
            }
            writer.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输入

<?xml version="1.0"?>
<BookCatalogue>
    <Book>
        <Title>HelloLord</Title>
        <Name>
            <first>New</first>
            <last>Earth</last>
        </Name>
        <ISBN>12345</ISBN>
    </Book>
    <Book>
        <Title>HelloWord</Title>
        <Name>
            <first>New</first>
            <last>Moon</last>
        </Name>
        <ISBN>12346</ISBN>
    </Book>
</BookCatalogue>

输出

<?xml version="1.0"?><BookCatalogue>
    <Book>
        <Title>OhLord</Title>
        <AuthorName>
            <!--auto generated comment-->
            <first>New</first>
            <last>Earth</last>
        </AuthorName>
        <ISBN>12345</ISBN>
    </Book>
    <Book>
        <Title>OhWord</Title>
        <AuthorName>
            <!--auto generated comment-->
            <first>New</first>
            <last>Moon</last>
        </AuthorName>
        <ISBN>12346</ISBN>
    </Book>
</BookCatalogue>

正如你所看到的,当修改远不止这样时,事情变得非常复杂,比如交换两个节点,根据其他几个节点的状态删除一个节点:删除价格高于平均价格的所有书籍

这种情况下的最佳解决方案是使用 xslt transformation 生成生成的 xml

【讨论】:

  • 请注意,此答案使用XMLEventWriter 而不是XMLStreamWriter。
  • 如果我想改变一个属性值怎么办?例如
猜你喜欢
  • 2010-09-30
  • 2011-07-07
  • 2012-08-23
  • 1970-01-01
  • 2018-09-23
  • 2013-11-28
  • 1970-01-01
  • 2019-10-01
  • 2011-06-04
相关资源
最近更新 更多