使用 Spring Batch StaxEventItemReader 处理非根 XML 元素

Processing non-root XML elements with Spring Batch StaxEventItemReader

我正在尝试使用 Spring 批处理从 XML 文件中读取非根元素。

我使用的批量配置包含:

如何配置 StAX 或 JAXB 以将非根元素解析为单个 Spring 批处理项目?

例如,假设我需要处理来自 Maven POM:

<dependency> 个元素
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>...</groupId>
  <artifactId>...</artifactId>
  <version>...</version>
  <packaging>...</packaging>

  <dependencies>
    <dependency>...</dependency>
    <dependency>...</dependency>
    <dependency>...</dependency>
    ...
  </dependencies>
</project>

使用以下代码(我只显示相关部分):

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
    @Bean
    public ItemReader<Dependency> reader(Jaxb2Marshaller marshaller) {
        return new StaxEventItemReaderBuilder<Dependency>().name("itemReader")
                .resource(inputFile)
                .addFragmentRootElements("dependency")
                .unmarshaller(marshaller)
                .build();
    }

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setPackagesToScan("org.apache.maven.pom._4_0");
        return marshaller;
    }
}

但我收到以下错误:

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://maven.apache.org/POM/4.0.0", local:"dependency"). Expected elements are <{http://maven.apache.org/POM/4.0.0}project>

我错过了什么?

pom 定义了一个自定义命名空间 xmlns="http://maven.apache.org/POM/4.0.0",因此您需要在 reader 的 bean 定义中使用它作为片段根元素名称的前缀:

@Bean
public ItemReader<Dependency> reader(Jaxb2Marshaller marshaller) {
    return new StaxEventItemReaderBuilder<Dependency>().name("itemReader")
            .resource(inputFile)
            .addFragmentRootElements("{http://maven.apache.org/POM/4.0.0}dependency")
            .unmarshaller(marshaller)
            .build();
}

我找到了一个解决方案:我需要调用 Jaxb2Marshaller.setMappedClass 来启用部分解组:

@Bean
public Jaxb2Marshaller marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setPackagesToScan("org.apache.maven.pom._4_0");
    marshaller.setMappedClass(Dependency.class); // ADD THIS LINE
    return marshaller;
}