针对多个 XML 节点的 Spring Batch JAXB XML 解组 [英] Spring Batch JAXB XML unmarshal targeting multiple XML nodes

查看:53
本文介绍了针对多个 XML 节点的 Spring Batch JAXB XML 解组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Spring Batch(和 Spring Boot)在 MultiResourceItemReader 中使用 StaxEventItemReader 读取 XML 文件.批处理读取器旨在针对 并处理/写入 XML 源中的每个寄存器.

I'm using Spring Batch (with Spring Boot) to read an XML file using StaxEventItemReader in a MultiResourceItemReader. Batch reader is intended to target <Receipt> and process/write for each register from the XML-source.

问题是我需要将

内容与每个寄存器一起编写.我能够配置 Jaxb2Marshaller 以便逐个读取收据(为每个寄存器获取对 process() 的回调),但我不知道如何才能我让 reader/unmarshaller 每次都读取
.

The problem I have is that I need to write the <Header> contents together with every register. I was able to configure Jaxb2Marshaller in order to read receipts one-by-one (getting a callback to process() for each register), but I cannot figure out how can I make reader/unmarshaller to read both the <Header> and a <Receipt> each time.

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

Maybe I have to create a ReceiptWrapper class to hold both header + receipt? In that case, how to instruct Jaxb2Marshaller to do so? And how to annotate Wrapper class? I'm a mess with annotations, reader.setFragmentRootElementNames() and marshaller.setClassesToBeBound().

有什么简单的方法可以实现吗?

Is there any simple way to achieve that?

目的是在每个寄存器的开头连接头.

The aim is to concatenate the header at the beginning of every register.

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

Note: I created Header and Receipt classes via Eclipse JAXB code generation from an XSD I generated.

这里是要读取的 XML 的结构:

Here is the structure of the XML to read:

<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);

推荐答案

最后我设法让它发挥作用.本质上,根据我的理解,要实现结果,您必须设置 StaxEventItemReader 将要生成的片段的根元素.

Finally I managed to make it work. In essence from what I've understood, to achieve the result, you must set the root elements of the fragments StaxEventItemReader is going to generate.

就我而言:

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

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

where HeaderType.class and ReceiptType.class are the JAXB-generated classes.

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

The trick was to define a common interface or base class for JAXB classes (e.g. MyXmlTargetElement) so that reader type declaration matches the unmarshalled objects:

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

这允许逐个读取元素(包括

)并且不需要包装类.

This allowed to read elements sequentially one-by-one (including <Header>) and no wrapper class was necessary.

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

Then in the process(MyXmlTargetElement item) method of Batch ItemProcessor, I checked for the actual type of item using instanceof and when a header has been read, set it to a private member field (lastHeader). Then, when a <Receipt> comes, you already have the previously header stored in that member.

这篇关于针对多个 XML 节点的 Spring Batch JAXB XML 解组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆