Сплит 1GB XML-файл с использованием Java
У меня есть XML-файл объемом 1 ГБ, как я могу разделить его на правильно сформированные XML-файлы меньшего размера, используя Java?
Вот пример:
<records>
<record id="001">
<name>john</name>
</record>
....
</records>
Благодарю.
4 ответа
Я бы использовал парсер StAX для этой ситуации. Это предотвратит одновременное чтение всего документа в память.
- Продвиньте XMLStreamReader к локальному корневому элементу подфрагмента.
- Затем вы можете использовать API javax.xml.transform для создания нового документа из этого фрагмента XML. Это продвинет XMLStreamReader до конца этого фрагмента.
- Повторите шаг 1 для следующего фрагмента.
Пример кода
Для следующего XML выведите каждый раздел "оператор" в файл с именем "значение атрибутов учетной записи":
<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));
}
}
}
Попробуйте это, используя 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>
Программное обеспечение не является бесплатным, но если оно сэкономит вам дневное кодирование, вы можете легко оправдать инвестиции. (Извинения за коммерческое предложение).
DOM, STax, SAX все будут делать, но есть свои плюсы и минусы.
- Вы не можете поместить все данные в память в случае DOM.
- Программирование управления легче в случае DOM, чем Stax, а затем SAX.
- Комбинация SAX и DOM - лучший вариант.
- Использование Framework, который уже делает это, может быть лучшим вариантом. Посмотрите на смукс. http://www.smooks.org/
Надеюсь это поможет
Я с уважением не согласен с Блезом Дафаном. 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++;
}
}
}
}