2013-05-10 4 views
7

私は巨大なXML(〜2GB)を持っており、新しい要素を追加して古い要素を変更する必要があります。例えば、私が持っている:StAXで巨大なXMLファイルを変更するには?

<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> 

アイデア

+0

十分なメモリがあれば、vtd-xmlは非常に簡単なコーディングを提供するオプションです。メモリを50%増やし、すべてをメモリに保存すると、DOMのように爆発しませんhttp://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf –

答えて

17

この

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(); 

ノート

新しいてFileWriter(ファイル、真の)あなたがほとんどそれを本当に必要としない、ファイルの末尾に追加され

試してみてください

XMLは、大文字と小文字を区別

+0

残念ながら、このコードは機能しません。 NetBeansでエラーが発生します: '原因:javax.xml.stream.XMLStreamException:ParseError at [row、col]:[4,2] メッセージ:XMLドキュメント構造は、同じエンティティ内で開始し、終了する必要があります。 \t com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:598) \t com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(XMLEventReaderImpl.java:83) librarian.controllers.BookCardController.saveToXML(BookCardController.java:140) \t ...もっと54」 で \t、さらに、それはファイルの内容をすべて削除します... – Eugene

+0

例外は何ですか?私は投稿前にあなたのXMLでそれをテストした –

+0

それを試したことがあります。同じ例外: '原因:javax.xml.stream.XMLStreamException:ParseError at [row、col]:[3,5] メッセージ:XMLドキュメント構造は、同じエンティティ内で開始し、終了する必要があります。 \t com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:598) \t com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(XMLEventReaderImpl.java:83) librarian.controllers.BookCardController.saveToXMLで\t(BookCardController.java:138) \t ... 54より」 私は本当に理由を知らないんだけど、さらにこのコードは、私のファイルを消去します。 – Eugene

3

なぜそれが動作するのかはかなり明確です。実際に行っていることは、既存のファイルを出力追加モードで開き、最後に要素を書き込むことです。それは明らかにあなたがしようとしていることと矛盾しています。

(私は、入力側が出力側がファイルの最後に追加された要素を表示する可能性が高いことに加え、Evgeniy Dorofeev'sたとえば、私が期待しているようなものがあります。問題は、テキストファイルを同時に読み書きしようとしたときに、読者またはライターがバッファリングの形式を明示的または暗黙的に使用すると、部分的な状態が見えます)。

これを修正するには、まず1つのファイルから読み込み、別のファイルに書き込む必要があります。追加は機能しません。次に、入力ファイルから読み込まれた要素、属性、内容などがで、出力ファイルにがコピーされていることを確認する必要があります。最後に、余分な要素を適切なポイントに追加する必要があります。理論的には不可能である


And is there any possibility to open the XML file in mode like RandomAccessFile, but write in it by StAX methods?

号。 XMLファイルの構造を「ランダム」ファイルでナビゲートできるようにするには、最初にすべてを解析し、すべての要素がどこにあるかのインデックスを作成する必要があります。これを行っても、XMLはファイル内に文字として格納され、ランダムアクセスではファイルの途中で文字の挿入や削除ができません。

XSLとSAXスタイルのパーサーを組み合わせるのが最善の方法でしょう。例えばこのIBMの記事の線に沿って何か:http://ibm.com/developerworks/xml/library/x-tiptrax

+0

そしてXMLファイルを開く可能性はありますかRandomAccessFileのようなモードでは、StAXメソッドでそれに書き込む? – Eugene

+0

理論的には可能です...私は推測します...しかし、私はあなたが望むものである既製のソリューションを認識していません。 –

1

JavaEEのtutoでたぶんこのStAXの読み取りおよび書き込みの例であるため、equalsIgnoreCase(「ブック」)は悪い考えですリアルに役立ちます:http://docs.oracle.com/javaee/5/tutorial/doc/bnbfl.html#bnbgq

あなたはここにチュートリアルの例をダウンロードすることができます。すばやくアクセスhttps://java.net/projects/javaeetutorial/downloads

は、言及の例はここにある:の.htm ">のhttp://read.pudn。com/downloads79/ebook/304101/javaeetutorial5/examples/stax/readnwrite/src/readnwrite/EventProducerConsumer.java_.htm

関連する問題