使用Stax解析合并多个文件不起作用

问题描述

我们正在使用Java 8和Java的XML Stream API在单个线程应用程序中合并两个xml。

下面是我尝试合并到最终xml的两个示例输入xml。在下面的两个示例xml中,html_tabs很常见 元素,因此在最终XML中必须只有一个html_tabs元素。

Sample XML 1
-----------------------
<?xml version='1.0' encoding='UTF-8'?>
<html_tabs lastRefreshDataDate="">
    <tab code="H_test_1" companyCode="H_test_1"
        id="H_test_1">
        <table>
            <tr><td>testing1 template</td></tr>
        </table>    
    </tab>  
</html_tabs>

Sample XML2
-----------------------
<?xml version='1.0' encoding='UTF-8'?>
<html_tabs lastRefreshDataDate="">
    <tab code="H_test_2" companyCode="H_test_2"
        id="H_test_2">
        <table>
            <tr><td>testing2 template</td></tr>
        </table>    
    </tab>  
</html_tabs>

Merged XML
---------------
<?xml version='1.0' encoding='UTF-8'?>
<html_tabs lastRefreshDataDate="">
 <tab code="H_test_1" companyCode="H_test_1"
        id="H_test_1">
        <table>
            <tr><td>testing1 template</td></tr>
        </table>    
 </tab>
 <tab code="H_test_2" companyCode="H_test_2"
        id="H_test_2">
        <table>
            <tr><td>testing2 template</td></tr>
        </table>    
 </tab> 
</html_tabs>

下面是我尝试通过跳过html_tabs元素来合并两个xml的代码。为了使问题简短,我已跳过导入语句。

public class MergeXML1 {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        XMLEventWriter eventWriter;
        XMLEventFactory eventFactory;
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        
        eventWriter = outputFactory.createXMLEventWriter(new FileOutputStream("testMerge1.xml"));
        eventFactory = XMLEventFactory.newInstance();
    
        // Create and write Start Tag
        XMLEvent statAbEvent = eventFactory.createStartDocument();
        eventWriter.add(statAbEvent);
        statAbEvent = eventFactory.createStartElement(StringUtils.EMPTY,StringUtils.EMPTY,"html_tabs");
        eventWriter.add(statAbEvent);
        statAbEvent = eventFactory.createAttribute("lastRefreshDataDate",StringUtils.EMPTY);
        eventWriter.add(statAbEvent);
        String[] filenames = new String[]{"4102530_1_statabfinsum.xml","4102530_2_statabfinsum.xml"};
        
        for (String filename : filenames) {
            XMLEventReader test = inputFactory.createXMLEventReader(filename,new FileInputStream(filename));
            System.out.println("read the first file : " + filename);
            
            while (test.hasNext()) {
                XMLEvent event = test.nextEvent();

                if (event.getEventType() != XMLEvent.START_DOCUMENT && event.getEventType() != XMLEvent.END_DOCUMENT) {
                    if (event.isstartElement()) {
                        StartElement startElement = event.asstartElement();
                        System.out.println("element name:" + startElement.getName().getLocalPart());
                        
                        if (!startElement.getName().getLocalPart().equals("html_tabs")) {
                            eventWriter.add(event);
                            continue;
                        } else {
                            continue;
                        }
                    }
                    eventWriter.add(event);
                }
            }
            
            test.close();
        }
        eventWriter.add(eventFactory.createEndElement("","","html_tabs"));
        eventWriter.add(eventFactory.createEndDocument());
        eventWriter.close();

    }

}

在尝试合并两个文件时使用上述源代码会引发异常。

Exception in thread "main" javax.xml.stream.XMLStreamException: Trying to output second root,<tab>
    at com.ctc.wstx.sw.BaseStreamWriter.throwOutputError(BaseStreamWriter.java:1589)
    at com.ctc.wstx.sw.BaseStreamWriter.throwOutputError(BaseStreamWriter.java:1596)
    at com.ctc.wstx.sw.BaseStreamWriter.reportNwfStructure(BaseStreamWriter.java:1624)
    at com.ctc.wstx.sw.BaseNsstreamWriter.checkStartElement(BaseNsstreamWriter.java:483)
    at com.ctc.wstx.sw.SimpleNsstreamWriter.writeStartOrEmpty(SimpleNsstreamWriter.java:257)
    at com.ctc.wstx.sw.BaseNsstreamWriter.writeStartElement(BaseNsstreamWriter.java:325)
    at org.codehaus.stax2.ri.Stax2EventWriterImpl.add(Stax2EventWriterImpl.java:100)
    at com.citi.research.distribution.tasks.downloadtasks.MergeXML1.main(MergeXML1.java:60)

由于出现异常,我无法找出上述代码出了什么问题。

谢谢您的帮助

解决方法

在检查代码的基础上,似乎您将最后一个EndElement从第一个文件复制到了输出,从而使您回到顶层。然后,当您尝试从第二个文件中写入(正确的)StartElement时,您试图将其插入根目录。

从第一个文件中过滤(即不写)EndElement

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...