2015-11-27 2 views
1

Jaxb2Marshaller (org.springframework.oxm.jaxb.Jaxb2Marshaller) является частью классов интеграции Spring/O Mapping Spring.Нечувствительный к регистру Jaxb2Marshaller

Я использую его в качестве unmarshaller из в StaxEventItemReader:

<bean class="org.springframework.batch.item.xml.StaxEventItemReader"> 
    <property name="marshaller"> 
     <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> 
      <property name="classesToBeBound"> 
       <list> 
        <value>xx.xx.xx.MyBean1</value> 
        <value>xx.xx.xx.MyBean2</value> 
        <value>xx.xx.xx.MyBean3</value> 
       </list> 
      </property> 
     </bean> 
    </property> 
</bean> 

MyBeanX классов annoted с javax.xml.bind.annotation аннотациями:

@XmlRootElement(name="MyBean1") 
@XmlType(propOrder = {"MyBean2", "MyBean2"}) 
public class MyBean1 implements Serializable { 

    private MyBean2 myBean2; 
    private MyBean3 myBean3; 

    @XmlElement(name="MyBean2") 
    public MyBean2 getMyBean2() { 
     return myBean2; 
    } 

    [...] 
} 

К сожалению, XMLs мне нужно маршализация может иметь разницу случая между их:

<MYBEAN1> 
    <MYBEAN2></MYBEAN2> 
    <MYBEAN3></MYBEAN3> 
</MYBEAN1>  

<MyBean1> 
    <MyBean2></MyBean2> 
    <MyBean3></MyBean3> 
</MyBean1> 

<mybean1> 
    <mybean2></mybean2> 
    <mybean3></mybean3> 
</mybean1> 

или больше вариантов ...

Теперь, я должен уметь разбирать эти XML-файлы в случайном порядке. То, что я видел до сих пор, было возможным, так это создать StreamReaderDelegate и передать через него XMLStreamReader либо конвертировать теги в нижний регистр, либо в верхний регистр.

XMLInputFactory xif = XMLInputFactory.newInstance(); 
XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("file.xml")); 
xsr = new MyStreamReaderDelegate(xsr); 

Где MyStreamReaderDelegate выглядит следующим образом:

private static class MyStreamReaderDelegate extends StreamReaderDelegate { 

    public MyStreamReaderDelegate(XMLStreamReader xsr) { 
     super(xsr); 
    } 

    @Override 
    public String getAttributeLocalName(int index) { 
     return super.getAttributeLocalName(index).toLowerCase(); 
    } 

    @Override 
    public String getLocalName() { 
     return super.getLocalName().toLowerCase(); 
    } 

} 

Моя проблема, я не знаю, какой метод для переопределения (и в каком классе), чтобы передать мой XML через этот делегат. Глядя на Jax2Marshaller исходный код, я обнаружил, что XMLStreamReader используется в методе unmarshalStaxSource(Unmarshaller jaxbUnmarshaller, Source staxSource):

private Object unmarshalStaxSource(Unmarshaller jaxbUnmarshaller, Source staxSource) throws JAXBException { 
    XMLStreamReader streamReader = StaxUtils.getXMLStreamReader(staxSource); 
    if (streamReader != null) { 
     return jaxbUnmarshaller.unmarshal(streamReader); 
    } 
    else { 
     XMLEventReader eventReader = StaxUtils.getXMLEventReader(staxSource); 
     if (eventReader != null) { 
      return jaxbUnmarshaller.unmarshal(eventReader); 
     } 
     else { 
      throw new IllegalArgumentException("StaxSource contains neither XMLStreamReader nor XMLEventReader"); 
     } 
    } 
} 

Так что мой вопрос, как я могу переопределить этот метод, чтобы добавить делегата?

ответ

1

Вы можете использовать версию 2.6+ от Moxy для достижения безупречной сортировки без учета регистра. Heres a link для конкретного улучшения, которое было сделано для конкретной цели.

Вам нужно будет установить для свойства UNMARSHALLING_CASE_INSENSITIVE значение true. Heres пример кода

final StaxEventItemReader<ProductDTO> itemReader = new StaxEventItemReader<>(); 
final Jaxb2Marshaller unMarshaller = new Jaxb2Marshaller(); 
final Map<String, Boolean> properties = Maps.newHashMap(); 
properties.put(UnmarshallerProperties.UNMARSHALLING_CASE_INSENSITIVE, Boolean.TRUE); 
unMarshaller.setUnmarshallerProperties(properties); 
itemReader.setUnmarshaller(unMarshaller); 
+0

Это решение работает только для eclipselink. Есть ли общий способ сделать это? Что, например, работает и для apache-wink? – bobbel

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