我使用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);
答案 0 :(得分:1)
最后我设法让它发挥作用。从我理解的内容来看,要实现结果,您必须设置要生成的片段StaxEventItemReader
的根元素。
就我而言:
fileReader.setFragmentRootElementNames(new String[]{ "Header", "Receipt" }
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(HeaderType.class, ReceiptType.class);
fileReader.setUnmarshaller(marshaller);
其中HeaderType.class
和ReceiptType.class
是JAXB生成的类。
诀窍是为JAXB类定义公共接口或基类(例如MyXmlTargetElement
),以便读取器类型声明与未编组的对象匹配:
StaxEventItemReader<MyXmlTargetElement> fileReader = new StaxEventItemReader<>();
这允许逐个顺序读取元素(包括<Header>
),并且不需要包装类。
然后在Batch ItemProcessor的process(MyXmlTargetElement item)
方法中,我使用instanceof检查了项目的实际类型,当读取标题时,将其设置为私有成员字段(lastHeader
)。然后,当<Receipt>
到来时,您已经在该成员中存储了先前的标题。