簡體   English   中英

如何通過 StAX 修改巨大的 XML 文件?

[英]How to modify a huge XML file by StAX?

我有一個巨大的 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>

有任何想法嗎?

試試這個

    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 區分大小寫

那么很清楚為什么它的行為方式如此。 您實際上正在做的是在輸出追加模式下打開現有文件並在最后寫入元素。 這顯然與您正在嘗試做的事情相矛盾。

(旁白:我很驚訝它的工作原理和它一樣好,因為輸入端可能會看到輸出端添加到文件末尾的元素。確實像 Evgeniy Dorofeev 的例子給出的例外是我期望的那種事情。問題是,如果您嘗試同時讀取和寫入文本文件,並且讀者或作者使用任何形式的緩沖,顯式或隱式,讀者很可能會看到部分狀態。)

要解決此問題,您必須從讀取一個文件並寫入另一個文件開始。 附加將不起作用。 然后,您必須安排將從輸入文件中讀取的元素、屬性、內容等復制到輸出文件中。 最后,您需要在適當的點添加額外的元素。


是否有可能以 RandomAccessFile 之類的模式打開 XML 文件,但通過 StAX 方法將其寫入?

不,這在理論上是不可能的。 為了能夠在“隨機”文件中瀏覽 XML 文件的結構,您首先需要解析整個內容並構建所有元素所在位置的索引。 即使您這樣做了,XML 仍然作為字符存儲在文件中,隨機訪問不允許您在文件中間插入和刪除字符。

也許最好的辦法是結合 XSL 和 SAX 風格的解析器; 例如,沿着這篇 IBM 文章的內容: http : //ibm.com/developerworks/xml/library/x-tiptrax

也許 JavaEE 教程中的這個 StAX 讀寫示例有幫助: http : //docs.oracle.com/javaee/5/tutorial/doc/bnbfl.html#bnbgq

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM