Код для использования StAX в Java - PullRequest
0 голосов
/ 24 июня 2011

У меня есть 200 МБ xml следующей формы:

      <school name = "some school">
        <class standard = "2A">
           <student>  
             ..... 
           </student>
           <student>  
             ..... 
           </student>
           <student>  
             ..... 
           </student>
         </class>
       </school>

Мне нужно разбить этот xml на несколько файлов , используя StAX, такой , что n учеников подпадают под каждыйXML-файл и структура сохраняется как <school>, затем <class> и <students> под ними.Атрибуты School и class также должны быть сохранены в результирующих xmls.

Вот код, который я использую:

XMLInputFactory inputFactory = XMLInputFactory.newInstance();

    String xmlFile = "input.XML";
    XMLEventReader reader = inputFactory.createXMLEventReader(new FileReader(xmlFile));

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);

    XMLEventWriter writer = null;

    int count = 0;

    QName name = new QName(null, "student");

    try {
        while (true) {
            XMLEvent event = reader.nextEvent();
            if (event.isStartElement()) {
                StartElement element = event.asStartElement();
                if (element.getName().equals(name)) {
                    String filename = "input"+ count + ".xml";
                    writer = outputFactory.createXMLEventWriter(new FileWriter(filename));
                    writeToFile(reader, event, writer);
                    writer.close();
                    count++;
                }
            }
            if (event.isEndDocument())
                break;
        }
    } catch (XMLStreamException e) {
        throw e;
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        reader.close();
    }

private static void writeToFile(XMLEventReader reader, XMLEvent startEvent, XMLEventWriter writer) throws XMLStreamException, IOException {

    StartElement element = startEvent.asStartElement();
    QName name = element.getName();
    int stack = 1;

    writer.add(element);

    while (true) {
        XMLEvent event = reader.nextEvent();
        if (event.isStartElement() && event.asStartElement().getName().equals(name))
            stack++;
        if (event.isEndElement()) {
            EndElement end = event.asEndElement();
            if (end.getName().equals(name)) {
                stack--;
                if (stack == 0) {
                    writer.add(event);
                    break;
                }
            }
        }
        writer.add(event);
    }

}

Пожалуйста, проверьте вызов функции writeToFile(reader, event, writer) в блоке try,Здесь объект чтения имеет только тег student.Мне нужно, чтобы у читателя были school, class, а затем n students.так что сгенерированный файл имеет структуру, аналогичную исходной, только с меньшим числом дочерних файлов на файл.

Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 24 июня 2011

Избавьтесь от лишних хлопот и времени и используйте структуру плоского XML-файла, которая у вас есть на данный момент, а затем создайте объекты POJO, которые будут представлять каждый объект, как вы заявили; Ученик , Школа и Класс .И затем с помощью Jaxb связать объекты с другой частью структуры.Затем вы можете эффективно разархивировать xml и получить доступ к различным элементам, как будто вы имеете дело с объектами SQL.

Используйте эту ссылку в качестве отправной точки Синтаксический анализ XML с JAXB

Одна проблема, делающая это таким образом, - потребление памяти.Для гибкости проектирования и управления памятью я предлагаю использовать SQL для этого.

0 голосов
/ 24 июня 2011

Я думаю, вы можете отслеживать список родительских событий до события стартового элемента «student» и передавать его в метод writeToFile ().Затем в методе writeToFile () вы можете использовать этот список для имитации событий «школа» и «класс».

0 голосов
/ 24 июня 2011

У вас есть код для определения, когда начинать новый файл, который я не изучал внимательно, но процесс завершения одного файла и запуска следующего определенно не завершен.

При достижении точки, в которой вы хотитечтобы завершить файл, вы должны сгенерировать конечные события для вложенных тегов <class> и <school> и для документа перед его закрытием.Когда вы запускаете новый файл, вам нужно сгенерировать стартовые события для того же самого после его открытия и перед повторным началом, чтобы скопировать студенческие события.

Чтобы правильно генерировать стартовые события, вам нужно сохранить соответствующиесобытия со входа.

...