Spring 批量 JAXB XML 解组目标多个 XML 节点
Spring Batch JAXB XML unmarshal targeting multiple XML nodes
我正在使用 Spring 批处理(使用 Spring 引导)在 MultiResourceItemReader
中使用 StaxEventItemReader
读取 XML 文件。批处理 reader 旨在针对 XML-source.
中每个寄存器的 <Receipt>
和 process/write
我的问题是我需要将<Header>
内容与每个寄存器一起写入。我能够配置 Jaxb2Marshaller
以读取收据 one-by-one(为每个寄存器获得对 process()
的回调),但我无法弄清楚如何使 reader/unmarshaller 到每次都阅读 <Header>
和 <Receipt>
。
也许我必须创建一个 ReceiptWrapper
class 来保存 header + 收据?那么,如何指示Jaxb2Marshaller
这样做呢?以及如何注释Wrapper class?
我对注释一团糟,reader.setFragmentRootElementNames()
和 marshaller.setClassesToBeBound()
.
有什么简单的方法可以实现吗?
目的是在每个寄存器的开头连接header。
注意: 我通过 Eclipse JAXB 代码生成从我生成的 XSD 创建了 Header 和收据 classes。
下面是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);
我终于成功了。从本质上讲,根据我的理解,要获得结果,您必须设置 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-generated classes.
诀窍是为 JAXB classes(例如 MyXmlTargetElement
)定义一个公共接口或基础 class,以便 reader 类型声明与未编组的 objects:
StaxEventItemReader<MyXmlTargetElement> fileReader = new StaxEventItemReader<>();
这允许按顺序读取元素 one-by-one(包括 <Header>
)并且不需要包装器 class。
然后在 Batch ItemProcessor 的 process(MyXmlTargetElement item)
方法中,我使用 instanceof 检查项目的实际类型,当 header 已被读取时,将其设置为私有成员字段(lastHeader
).然后,当 <Receipt>
出现时,您已经在该成员中存储了之前的 header。
我正在使用 Spring 批处理(使用 Spring 引导)在 MultiResourceItemReader
中使用 StaxEventItemReader
读取 XML 文件。批处理 reader 旨在针对 XML-source.
<Receipt>
和 process/write
我的问题是我需要将<Header>
内容与每个寄存器一起写入。我能够配置 Jaxb2Marshaller
以读取收据 one-by-one(为每个寄存器获得对 process()
的回调),但我无法弄清楚如何使 reader/unmarshaller 到每次都阅读 <Header>
和 <Receipt>
。
也许我必须创建一个 ReceiptWrapper
class 来保存 header + 收据?那么,如何指示Jaxb2Marshaller
这样做呢?以及如何注释Wrapper class?
我对注释一团糟,reader.setFragmentRootElementNames()
和 marshaller.setClassesToBeBound()
.
有什么简单的方法可以实现吗?
目的是在每个寄存器的开头连接header。
注意: 我通过 Eclipse JAXB 代码生成从我生成的 XSD 创建了 Header 和收据 classes。
下面是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);
我终于成功了。从本质上讲,根据我的理解,要获得结果,您必须设置 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-generated classes.
诀窍是为 JAXB classes(例如 MyXmlTargetElement
)定义一个公共接口或基础 class,以便 reader 类型声明与未编组的 objects:
StaxEventItemReader<MyXmlTargetElement> fileReader = new StaxEventItemReader<>();
这允许按顺序读取元素 one-by-one(包括 <Header>
)并且不需要包装器 class。
然后在 Batch ItemProcessor 的 process(MyXmlTargetElement item)
方法中,我使用 instanceof 检查项目的实际类型,当 header 已被读取时,将其设置为私有成员字段(lastHeader
).然后,当 <Receipt>
出现时,您已经在该成员中存储了之前的 header。