Разделение большого XML-файла на небольшие фрагменты на основе повторяющихся элементов

Рассмотрим следующий XML с данными размером 500 МБ.

<?xml version="1.0" encoding="UTF-8"?>
<Parents>
  <process  Child ="A">...</process>
  <process  Child="B">...</process>
  <process  Child="A">...</process>
  <process  Child="C">..</process>
  <process Child=...
  </process>
 <\Parents>

Этот xml имеет несколько дочерних атрибутов с тегом «A» или «B» или другим. Я хочу создать отдельный XML для «A», «B», «C» или других, таких как expamle_A.xml, example_B.xml и т. д. Ниже кода создает отдельный xml для каждого дочернего атрибута, это означает, что если у нас есть 500 дочерних атрибутов, он создает 500 xml.

public static void main(String args[]) {
        try {
            VTDGen v = new VTDGen();
            if (v.parseFile("C:\\..\\example.xml", true)) {
                VTDNav vn = vg.getNav();
                AutoPilot ap = new AutoPilot(vn);
                ap.selectXPath("/Parents/child");
                int  chunk = 0;
                while (( ap.evalXPath()) != -1) {
                    long frag = vn.getElementFragment();
                    (new FileOutputStream("C:\\....\\result" + chunk + ".xml")).write(vn.getXML().getBytes(), (int) frag,
                            (int) (frag >> 32));
                    chunk++;
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
}

Теперь дело в том, что я хочу разделить файл на основе дочернего атрибута одной и той же группы, например, все дочерние элементы «A» должны быть в файле example_A.xml таким же образом для B, C и другие.


person Anupam Alok    schedule 20.07.2017    source источник
comment
в чем вопрос?   -  person Sharon Ben Asher    schedule 20.07.2017
comment
О, извините, действительно пропустил эту часть, я хочу разлить XML на основе имени ребенка, что означает, что expamle_A.xml должен содержать все атрибуты ‹Child =A›...‹/Child›   -  person Anupam Alok    schedule 20.07.2017
comment
кажется, вы уже используете XPath. так в чем проблема опять??   -  person Sharon Ben Asher    schedule 20.07.2017
comment
@sharon Я не могу сгруппировать дочерние узлы в один файл, скажем, в этом файле 30 узлов с Child = A, поэтому для этого создается 30 файлов, но я хочу, чтобы они были в одном файле.   -  person Anupam Alok    schedule 20.07.2017
comment
хорошо, теперь картина яснее, это должно перейти к вопросу о том, что вы пробовали до сих пор   -  person Sharon Ben Asher    schedule 20.07.2017
comment
вам нужно записать заголовок и хвост корневого элемента в каждый файл.   -  person vtd-xml-author    schedule 20.07.2017
comment
какое имя атрибута связывает A или B?   -  person vtd-xml-author    schedule 20.07.2017
comment
@vtd-xml-author свой процесс ‹process child=A›......‹/process›   -  person Anupam Alok    schedule 20.07.2017
comment
@vtd-xml-author, это то, что я хочу, но не могу этого добиться, так как каждый дочерний файл должен быть похож на A, файл должен быть «Родители» ‹ Дочерний = A › ... ‹ / Дочерний › ‹ Дочерний = A ›. ..‹/Child›‹/Parents› для файла B должно быть ‹Parents› ‹Child =B›...‹/Child›‹Child =B›…‹/Child›‹/Parents›   -  person Anupam Alok    schedule 20.07.2017
comment
‹child=b› не является допустимым xml... вы имели в виду ‹process child=A›   -  person vtd-xml-author    schedule 20.07.2017
comment
Вы можете использовать vn.toRawString(VTDNav.TOKEN_ATTR_NAME), чтобы узнать текущее имя атрибута, и использовать true с потоком вывода файлов, чтобы не перезаписывать файл каждый раз.   -  person Sadiq Ali    schedule 20.07.2017
comment
@vtd-xml-author, я имел в виду ‹process child=A›   -  person Anupam Alok    schedule 20.07.2017


Ответы (1)


Это очень простая модификация вашего существующего кода. На самом деле есть несколько способов сделать это. Я просто покажу вам один из них: путем явного сравнения attr val с использованием методов VTDNav getAttrVal().

public static void main1(String args[]) {
    try {
        VTDGen vg = new VTDGen();
        if (vg.parseFile("C:\\..\\example.xml", true)) {
            VTDNav vn = vg.getNav();
            AutoPilot ap = new AutoPilot(vn);
            ap.selectXPath("/Parents/process");
            int  chunk = 0;
            FileOutputStream fopsA=(new FileOutputStream("C:\\....\\resultA" + chunk + ".xml"));
            fopsA.write("<Parent>\n".getBytes());
            FileOutputStream fopsB=(new FileOutputStream("C:\\....\\resultB" + chunk + ".xml"));
            while (( ap.evalXPath()) != -1) {
                long frag = vn.getElementFragment();
                int i=vn.getAttrVal("Child");
                if (i==-1) throw new NavException("unexpected result");
                if  (vn.compareTokenString(i,"A")==0){

                    fopsA.write(vn.getXML().getBytes(), (int) frag,
                        (int) (frag >> 32));

                }else if  (vn.compareTokenString(i,"B")==0){

                    fopsB.write(vn.getXML().getBytes(), (int) frag,
                            (int) (frag >> 32));
                }
                chunk++;
            }

            fopsA.write("</Parent>\n".getBytes());
            fopsB.write("</Parent>\n".getBytes());
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
person vtd-xml-author    schedule 20.07.2017
comment
Спасибо, хорошо объяснили, но единственная проблема в том, что если у нас есть 100 различных атрибутов дочернего элемента, нам нужно предоставить еще 100, если условие для этого, например, для A, B, C, D и т. д., чтобы записать его в другой файл. Есть ли у него какой-либо общий способ, например, где я могу предоставить цикл для чтения всех атрибутов с A и записи его в файл аналогично для B, C и так далее. - person Anupam Alok; 20.07.2017
comment
как видите, есть способы автоматизировать этот процесс... но это больше похоже на вашу домашнюю работу, чем на мою. Согласовано? - person vtd-xml-author; 20.07.2017