3

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

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

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

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

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

4

1 回答 1

3

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

下面的代码重命名NameAuthorName添加注释

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 转换生成生成的 xml

于 2013-08-29T23:58:00.413 回答