使用XMLStreamWriter更新XML

时间:2013-08-29 21:19:54

标签: java xml stax xmlstreamreader

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

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

现在我想将此更新的用户对象放回原始XML中。我认为我可以将用户对象编组为字符串,并将字符串放在输入xml中的正确位置。但是我无法使用STAX类 - XMLStreamWriter

来实现它

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

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

1 个答案:

答案 0 :(得分:3)

如果您需要更改特定值,如文本内容/标签名称等,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