8

我有一个巨大的 XML (~2GB),我需要添加新元素并修改旧元素。例如,我有:

<books>
    <book>....</book>
    ...
    <book>....</book>
</books>

并想得到:

<books>
   <book>
      <index></index>
      ....
   </book>
   ...
   <book>
      <index></index>
      ....
   </book>
</books>

我使用了以下代码:

XMLInputFactory inFactory = XMLInputFactory.newInstance();
XMLEventReader eventReader = inFactory.createXMLEventReader(new FileInputStream(file));
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter(new FileWriter(file, true));
while (eventReader.hasNext()) {
   XMLEvent event = eventReader.nextEvent();
   if (event.getEventType() == XMLEvent.START_ELEMENT) {
      if (event.asStartElement().getName().toString().equalsIgnoreCase("book")) {
          writer.writeStartElement("index");
          writer.writeEndElement();
       }
    }
}
writer.close();

但结果如下:

<books>
   <book>....</book>
   ....
   <book>....</book>
</books><index></index>

有任何想法吗?

4

3 回答 3

20

尝试这个

    XMLInputFactory inFactory = XMLInputFactory.newInstance();
    XMLEventReader eventReader = inFactory.createXMLEventReader(new FileInputStream("1.xml"));
    XMLOutputFactory factory = XMLOutputFactory.newInstance();
    XMLEventWriter writer = factory.createXMLEventWriter(new FileWriter(file));
    XMLEventFactory eventFactory = XMLEventFactory.newInstance();
    while (eventReader.hasNext()) {
        XMLEvent event = eventReader.nextEvent();
        writer.add(event);
        if (event.getEventType() == XMLEvent.START_ELEMENT) {
            if (event.asStartElement().getName().toString().equalsIgnoreCase("book")) {
                writer.add(eventFactory.createStartElement("", null, "index"));
                writer.add(eventFactory.createEndElement("", null, "index"));
            }
        }
    }
    writer.close();

笔记

new FileWriter(file, true) 附加到文件的末尾,你几乎不需要它

equalsIgnoreCase("book") 是个坏主意,因为 XML 区分大小写

于 2013-05-10T10:21:12.687 回答
5

好吧,很清楚为什么它的行为方式如此。您实际上正在做的是以输出追加模式打开现有文件并在最后写入元素。这显然与您正在尝试做的事情相矛盾。

(旁白:鉴于输入端很可能会看到输出端添加到文件末尾的元素,我很惊讶它的工作原理。事实上,像 Evgeniy Dorofeev 的例子给出的例外是我期望的那种事情问题是,如果您尝试同时读取和写入文本文件,并且读取器或写入器使用任何形式的显式或隐式缓冲,则读者可能会看到部分状态。)

要解决此问题,您必须首先从一个文件读取并写入另一个文件。附加将不起作用。然后你必须安排将从输入文件中读取的元素、属性、内容等复制到输出文件中。最后,您需要在适当的位置添加额外的元素。


是否有可能以 RandomAccessFile 之类的模式打开 XML 文件,但通过 StAX 方法写入它?

不,这在理论上是不可能的。为了能够在“随机”文件中浏览 XML 文件的结构,您首先需要解析整个内容并建立所有元素所在位置的索引。即使您这样做了,XML 仍然作为字符存储在文件中,并且随机访问不允许您在文件中间插入和删除字符。

也许您最好的选择是将 XSL 和 SAX 样式解析器结合起来;例如,与这篇 IBM 文章类似的内容:http: //ibm.com/developerworks/xml/library/x-tiptrax

于 2013-05-10T10:21:11.357 回答
0

也许 JavaEE 教程中的这个 StAX 读写示例有帮助:http ://docs.oracle.com/javaee/5/tutorial/doc/bnbfl.html#bnbgq

您可以在此处下载教程示例:https ://java.net/projects/javaeetutorial/downloads

于 2013-06-07T19:22:18.707 回答