2016-12-20 3 views
0

Я использую Spring Batch (с Spring Boot) для чтения XML-файла с использованием StaxEventItemReader в MultiResourceItemReader. Пакетное считывание предназначено для задания <Receipt> и обработки/записи для каждого регистра из XML-источника.Spring Batch JAXB XML немаршален для нескольких узлов XML

проблема У меня есть то, что мне нужно написать содержимое <Header> вместе с каждым регистром. Мне удалось настроить Jaxb2Marshaller, чтобы читать квитанции один за другим (получение обратного вызова до process() для каждого регистра), но я не могу понять, как я могу заставить читателя/unmarshaller читать как <Header>, так и <Receipt> каждый раз.

Возможно, мне нужно создать класс ReceiptWrapper для хранения как заголовка + квитанции? В этом случае, как это сделать Jaxb2Marshaller? И как комментировать класс Wrapper? Я беспорядок с аннотациями, reader.setFragmentRootElementNames() и marshaller.setClassesToBeBound().

Есть ли простой способ достичь этого?

Цель состоит в том, чтобы объединить заголовок в начале каждого регистра.

Примечание: Я создал классы заголовков и чеков с помощью генерации кода Eclipse JAXB из генерируемого XSD.

Вот структура 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

Наконец мне удалось заставить его работать. По сути, из того, что я понял, для достижения результата необходимо установить корневые элементы фрагментов 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) так, что объявление типа читателя соответствует unmarshalled объектов:

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

Это позволило читать элементы последовательно один за другим (включая <Header>), и не требовалось никакого класса обертки.

Затем в методе Batch ItemProcessor process(MyXmlTargetElement item) я проверил фактический тип элемента, используя instanceof, и когда заголовок был прочитан, установите его в поле частного члена (lastHeader). Затем, когда приходит <Receipt>, у вас уже есть заголовок, ранее сохраненный в этом элементе.

Смежные вопросы