Spring Batch JAXB XML解组多个XML节点

时间:2016-12-20 15:09:09

标签: java spring-boot jaxb spring-batch jaxb2

我使用Spring Batch(使用Spring Boot)在StaxEventItemReader中使用MultiResourceItemReader读取XML文件。批处理阅读器旨在针对来自XML源的每个寄存器<Receipt>和处理/写入。

问题我有需要将<Header>内容与每个寄存器一起编写。我能够配置Jaxb2Marshaller以逐个读取收据(为每个寄存器回复process()),但我无法弄清楚如何让读者/解组者同时阅读每次<Header><Receipt>

也许我必须创建一个ReceiptWrapper类来保存标题+收据?在这种情况下,如何指示Jaxb2Marshaller这样做?以及如何注释Wrapper类? 我的注释很混乱,reader.setFragmentRootElementNames()marshaller.setClassesToBeBound()

有没有简单的方法来实现这一目标?

目的是在每个寄存器的开头连接标题。

注意:我通过生成的XSD生成Eclipse JAXB代码创建了Header和Receipt类。

以下是要阅读的XML的结构:

<ProcesosEIAC xsi:schemaLocation="http://www.tirea.es/EIAC/ProcesosEIAC ProcesosEIAC.xsd" xmlns="http://www.tirea.es/EIAC/ProcesosEIAC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
    <!-- [...] -->
</Header>
<Objects>
    <Receipt>
        <!-- [...] -->
    </Receipt>
    [...]
    <Receipt>
        <!-- [...] -->
    </Receipt>
</Objects>

以下是我所拥有的摘录:

// Don't know how this should be...
fileReader.setFragmentRootElementNames(new String[]{"ProcesosEIAC", "Header", "Receipt"});

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(ReceiptWrapper.class /*, HeaderType.class, ReceiptType.class*/);
fileReader.setUnmarshaller(marshaller);

1 个答案:

答案 0 :(得分:1)

最后我设法让它发挥作用。从我理解的内容来看,要实现结果,您必须设置要生成的片段StaxEventItemReader的根元素。

就我而言:

fileReader.setFragmentRootElementNames(new String[]{ "Header", "Receipt" }
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(HeaderType.class, ReceiptType.class);
fileReader.setUnmarshaller(marshaller);

其中HeaderType.classReceiptType.class是JAXB生成的类。

诀窍是为JAXB类定义公共接口或基类(例如MyXmlTargetElement),以便读取器类型声明与未编组的对象匹配:

StaxEventItemReader<MyXmlTargetElement> fileReader = new StaxEventItemReader<>();

这允许逐个顺序读取元素(包括<Header>),并且不需要包装类。

然后在Batch ItemProcessor的process(MyXmlTargetElement item)方法中,我使用instanceof检查了项目的实际类型,当读取标题时,将其设置为私有成员字段(lastHeader)。然后,当<Receipt>到来时,您已经在该成员中存储了先前的标题。