繁体   English   中英

如何在Java中合并两个XML

[英]How to Merge two XMLs in Java

我试图在Java中合并两个xmls。 我正在使用STaX API来编写这些XML。 我在互联网上搜索了很多关于如何合并xmls的内容,但似乎没有像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>

我有一个适合我的解决方案。 现在专家,请告知这是否可行。

谢谢,-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();

一般的解决方案仍然是XSLT,但你需要先将两个文件合并为一个大的XML,然后使用包装元素(XSLT与一个输入源一起工作)。

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

然后只需对匹配=“// TestCase”执行XSLT,并将所有测试用例转储出来,忽略它们所属的测试用例块。

在尝试之前不要担心性能。 JAva中的XML API比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内在这个(小)例子上编译和执行的。

如果结构足够常规以便您可以使用数据绑定,我实际上会考虑使用JAXB将两个文件中的XML绑定到对象中,然后合并对象,将其序列化为XML。 如果文件大小很大,你也可以绑定子树; 为此,您使用XMLStreamReader(来自Stax api,javax.xml.stream)迭代到作为根的元素,将该元素(及其子元素)绑定到您想要的对象,迭代到下一个根元素。

检查XmlCombiner ,它是一个以完全这种方式实现XML合并的Java库。 它松散地基于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);

免责声明:我是图书馆的作者。

我认为XSLT和SAX可以成为一种解决方案。

如果您使用Stream,STaX是解决方案,我会阅读Sun教程,我认为非常有帮助: Sun Tutorail on STaX

再见

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM