Как объединить два XML в Java - PullRequest
6 голосов
/ 15 апреля 2011

Я пытаюсь объединить два xmls в Java. Я использую STaX API для написания этих XML. Я много искал в интернете, как объединить xmls, но ни один не выглядит так просто, как C # . Есть ли прямой способ сделать это в Java с использованием StAX? Вероятно, xslt не будет правильным решением, поскольку размер файла может быть большим.

File1.xml

<TestCaseBlock>
    <TestCase TestCaseID="1">
        <Step ExecutionTime="2011-03-29 12:08:31 EST">
            <Status>Passed</Status>
            <Description>foo</Description>
            <Expected>foo should pass</Expected>
            <Actual>foo passed</Actual>
        </Step>
       </TestCase>
</TestCaseBlock> 

File2.xml

<TestCaseBlock>
    <TestCase TestCaseID="2">
        <Step ExecutionTime="2011-03-29 12:08:32 EST">
            <Status>Failed</Status>
            <Description>test something</Description>
            <Expected>something expected</Expected>
            <Actual>not as expected</Actual>
        </Step>
    </TestCase>
</TestCaseBlock>

Merged.xml

<TestCaseBlock>
<TestCase TestCaseID="1">
    <Step ExecutionTime="2011-03-29 12:08:33 EST">
        <Status>Passed</Status>
        <Description>foo</Description>
        <Expected>foo should pass</Expected>
        <Actual>foo passed</Actual>
    </Step>
</TestCase>
<TestCase TestCaseID="2">
    <Step ExecutionTime="2011-03-29 12:08:34 EST">
        <Status>Failed</Status>
        <Description>test something</Description>
        <Expected>something expected</Expected>
        <Actual>not as expected</Actual>
    </Step>
</TestCase>
</TestCaseBlock>

Ответы [ 5 ]

3 голосов
/ 18 апреля 2011

У меня есть решение, которое работает для меня.Теперь эксперты, пожалуйста, сообщите, если это путь.

Спасибо, -Nilesh

    XMLEventWriter eventWriter;
    XMLEventFactory eventFactory;
    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    XMLInputFactory inputFactory = XMLInputFactory.newInstance();
    eventWriter = outputFactory.createXMLEventWriter(new FileOutputStream("testMerge1.xml"));
    eventFactory = XMLEventFactory.newInstance();
    XMLEvent newLine = eventFactory.createDTD("\n");                
    // Create and write Start Tag
    StartDocument startDocument = eventFactory.createStartDocument();
    eventWriter.add(startDocument);
    eventWriter.add(newLine);
    StartElement configStartElement = eventFactory.createStartElement("","","TestCaseBlock");
    eventWriter.add(configStartElement);
    eventWriter.add(newLine);
    String[] filenames = new String[]{"test1.xml", "test2.xml","test3.xml"};
    for(String filename:filenames){
           XMLEventReader test = inputFactory.createXMLEventReader(filename,
                             new FileInputStream(filename));
        while(test.hasNext()){
            XMLEvent event= test.nextEvent();
        //avoiding start(<?xml version="1.0"?>) and end of the documents;
        if (event.getEventType()!= XMLEvent.START_DOCUMENT && event.getEventType() != XMLEvent.END_DOCUMENT)
                eventWriter.add(event);         
        eventWriter.add(newLine);
            test.close();
        }           
    eventWriter.add(eventFactory.createEndElement("", "", "TestCaseBlock"));
    eventWriter.add(newLine);
    eventWriter.add(eventFactory.createEndDocument());
    eventWriter.close();
2 голосов
/ 15 апреля 2011

Общим решением по-прежнему будет XSLT, но вам нужно сначала объединить два файла в один большой XML с элементом-оберткой (XSLT работает с одним входным источником).

<root>
    <TestCaseBlock>
        <TestCase TestCaseID="1">
        ...
        </TestCase>
    </TestCaseBlock>
    <TestCaseBlock>
        <TestCase TestCaseID="2">
        ...
        </TestCase>
    </TestCaseBlock>
</root>

Затем просто выполните XSLT для match = "// TestCase" и выгрузите все тестовые наборы, игнорируя, к какому блоку тестовых блоков они принадлежат.

И не беспокойтесь опроизводительность, пока вы не попробовали.XML API в JAva становятся намного лучше, чем в 2003 году.

Это таблица стилей, которая вам нужна:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
            <TestCaseBlock>
                <xsl:apply-templates/>
            </TestCaseBlock>
    </xsl:template>

    <xsl:template match="//TestCase">
          <xsl:copy-of select="."/> 
    </xsl:template>

</xsl:stylesheet>

Протестировано, работает.

Кстати, этот XSLT был скомпилировани выполнено на этом (маленьком) примере за 1мс.

1 голос
/ 17 апреля 2011

Если структура достаточно регулярна, чтобы вы могли использовать привязку данных, я бы на самом деле рассмотрел возможность связывания XML из обоих файлов в объекты с использованием JAXB, а затем слияния объектов и сериализации обратно в XML. Если размеры файлов велики, вы также можете просто связать поддеревья; для этого вы используете XMLStreamReader (от Stax api, javax.xml.stream) для итерации до элемента, являющегося корнем, привязки этого элемента (и его дочерних элементов) к нужному объекту, итерации к следующему корневому элементу.

0 голосов
/ 03 декабря 2014

Проверьте XmlCombiner , которая является библиотекой Java, которая реализует слияние XML именно таким образом.Он основан на похожей функциональности, предоставляемой библиотекой plexus-utils .

В вашем случае теги также должны совпадать на основании значения атрибута TestCaseID.Вот полный пример:

import org.atteo.xmlcombiner.XmlCombiner;

// create combiner
XmlCombiner combiner = new XmlCombiner("TestCaseID");
// combine files
combiner.combine(firstFile);
combiner.combine(secondFile);
// store the result
combiner.buildDocument(resultFile);

Отказ от ответственности: я являюсь автором библиотеки.

0 голосов
/ 16 апреля 2011

Я думаю, что XSLT и SAX могли бы быть решением.

Если вы будете работать с Stream в качестве решения STaX, я прочитал учебник Sun, который мне кажется очень полезным: Sun Tutorail на STaX

Bye

...