Сплит 1GB Xml файл с использованием Java

У меня есть 1GB Xml файл, как я могу разбить его на хорошо сформированные Xml файлы меньшего размера, используя Java?

Вот пример:

<records>
  <record id="001">
    <name>john</name>
  </record>
 ....
</records>

Спасибо.

Ответ 1

Я бы использовал синтаксический анализатор StAX для этой ситуации. Это предотвратит чтение всего документа за один раз.

  • Предоставьте XMLStreamReader локальному корневому элементу под-фрагмента.
  • Затем вы можете использовать javax.xml.transform API для создания нового документа из этого фрагмента XML. Это ускорит XMLStreamReader до конца этого фрагмента.
  • Повторите шаг 1 для следующего фрагмента.

Пример кода

Для следующего XML выведите каждый раздел "statement" в файл с именем "Значение атрибута учетной записи":

<statements>
   <statement account="123">
      ...stuff...
   </statement>
   <statement account="456">
      ...stuff...
   </statement>
</statements>

Это можно сделать с помощью следующего кода:

import java.io.File;
import java.io.FileReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;

public class Demo {

    public static void main(String[] args) throws Exception  {
        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));
        xsr.nextTag(); // Advance to statements element

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        while(xsr.nextTag() == XMLStreamConstants.START_ELEMENT) {
            File file = new File("out/" + xsr.getAttributeValue(null, "account") + ".xml");
            t.transform(new StAXSource(xsr), new StreamResult(file));
        }
    }

} 

Ответ 2

Попробуйте это, используя Saxon-EE 9.3.

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:mode streamable="yes"/>
    <xsl:template match="record">
      <xsl:result-document href="record-{@id}.xml">
        <xsl:copy-of select="."/>
      </xsl:result-document>
    </xsl:template>
</xsl:stylesheet>

Программное обеспечение не является бесплатным, но если оно экономит вам дневную кодировку, вы легко можете оправдать инвестиции. (Извинения за шаг продаж).

Ответ 3

DOM, STax, SAX все будет делать, но есть свои плюсы и минусы.

  • Вы не можете поместить все данные в память в случае DOM.
  • Управление программированием проще в случае DOM, затем Stax, а затем SAX.
  • Комбинация SAX и DOM - лучший вариант.
  • Использование Framework, который уже делает это, может быть лучшим вариантом. Взгляните на smooks. http://www.smooks.org

Надеюсь, что это поможет

Ответ 4

Я почтительно не согласен с Блейзом Доханом. SAX не только трудно использовать, но и очень медленно. С VTD-XML вы можете не только использовать XPath для упрощения логики обработки (10-кратное сокращение кода очень часто), но и намного быстрее, потому что нет избыточного преобразования кодирования/декодирования. Ниже приведен код java с vtd-xml

import java.io.FileOutputStream;
import com.ximpleware.*; 

public class split {
    public static void main(String[] args) throws Exception {       
        VTDGen vg = new VTDGen();       
        if (vg.parseHttpUrl("c:\\xml\\input.xml", true)) {
            VTDNav vn = vg.getNav();
            AutoPilot ap = new AutoPilot(vn);
            ap.selectXPath("/records/record");
            int i=-1,j=0;
            while ((i = ap.evalXPath()) != -1) {
            long l=vn.getElementFragment();
                (new FileOutputStream("out"+j+".xml")).write(vn.getXML().getBytes(), (int)l,(int)(l>>32));
                j++;
            }
        }
    }
}