6

Java で 2 つの xml をマージしようとしています。これらの XML を記述するために STaX API を使用しています。xml をマージする方法についてインターネットで多くのことを検索しましたが、C#ほど簡単なものはないようです。StAXを使用してJavaでこれを行う簡単な方法はありますか? ファイルサイズが大きくなる可能性があるため、おそらく 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>
4

6 に答える 6

3

私には自分に合った解決策があります。専門家の皆さん、これが進むべき道かどうかアドバイスをください。

ありがとう - ニレッシュ

    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();
于 2011-04-17T23:52:13.983 に答える
2

一般的な解決策はXSLTですが、最初にラッパー要素を使用して2つのファイルを1つの大きなXMLに結合する必要があります(XSLTは1つの入力ソースで動作します)。

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

次に、match = "// TestCase"に対してXSLTを実行し、すべてのテストケースをダンプして、それらが属するテストケースブロックを無視します。

試してみるまで、パフォーマンスについて心配する必要はありません。JAvaのXMLAPIは、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は、この(小さな)例で1msでコンパイルおよび実行されました。

于 2011-04-15T19:53:25.843 に答える
1

構造が規則的でデータ バインディングを使用できる場合は、JAXB を使用して両方のファイルの XML をオブジェクトにバインドし、オブジェクトをマージして XML としてシリアル化することを実際に検討します。ファイル サイズが大きい場合は、サブツリーをバインドすることもできます。このために、XMLStreamReader (Stax api、javax.xml.stream から) を使用して、ルートである要素に反復し、その要素 (およびその子) を目的のオブジェクトにバインドし、次のルート要素に反復します。

于 2011-04-16T20:04:13.713 に答える
0

XSLT と SAX が解決策になると思います。

STaX がソリューションである Stream を使用する場合は、Sun のチュートリアルを読みます。非常に役立つと思います: Sun Tutorail on STaX

さよなら

于 2011-04-15T20:00:32.883 に答える