Обработка некорневых XML-элементов с помощью пакета Spring StaxEventItemReader

#spring #spring-boot #jaxb #spring-batch #stax

#spring #spring-boot #jaxb #spring-batch #stax

Вопрос:

Я пытаюсь прочитать некорневые элементы из XML-файла с помощью Spring Batch.

Конфигурация пакета, которую я использую, содержит:

  • a StaxEventItemReader , настроенный для чтения <dependency> элементов
  • Jaxb2Marshaller привязка к классам, созданным JAXB

Как мне настроить StAX или JAXB для анализа некорневых элементов как отдельных элементов пакета Spring?

Например, допустим, мне нужно обработать <dependency> элементы из Maven POM:

 <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: неожиданный элемент (uri:»http://maven.apache.org/POM/4.0.0 «, local:»зависимость»). Ожидаемые элементы <{http://maven.apache.org/POM/4.0.0 }проект>

Чего мне не хватает?

Ответ №1:

Я нашел решение: мне нужно было позвонить 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;
}
 

Ответ №2:

Pom определяет пользовательское пространство xmlns="http://maven.apache.org/POM/4.0.0" имен, поэтому вам нужно добавить к нему префикс имени корневого элемента фрагмента в определении компонента вашего читателя:

 @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();
}
 

Комментарии:

1. К сожалению, это изменение не возымело никакого эффекта: я продолжаю получать ту же ошибку. Я считаю, что это не проблема с пространством имен, поскольку в сообщении об ошибке указано правильное пространство имен.