不区分大小写的 Jaxb2Marshaller
Case Insensitive Jaxb2Marshaller
Jaxb2Marshaller (org.springframework.oxm.jaxb.Jaxb2Marshaller) 是 Spring 的 O/X 映射集成的一部分 classes.
我用它作为 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
classes 有 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();
}
}
我的问题是我不知道要覆盖什么方法(以及在哪个 class 中)来通过此委托传递我的 XML。查看Jax2Marshaller
源码,发现在方法unmarshalStaxSource(Unmarshaller jaxbUnmarshaller, Source staxSource)
:
中使用了一个XMLStreamReader
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");
}
}
}
所以我的问题是,如何覆盖此方法以添加委托?
您可以使用 2.6+ 版本的 Moxy 来实现不区分大小写的编组。这是针对特定目的进行的特定增强的 link。
您必须将 UNMARSHALLING_CASE_INSENSITIVE
属性 设置为 true。这是一些示例代码
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);
Jaxb2Marshaller (org.springframework.oxm.jaxb.Jaxb2Marshaller) 是 Spring 的 O/X 映射集成的一部分 classes.
我用它作为 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
classes 有 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();
}
}
我的问题是我不知道要覆盖什么方法(以及在哪个 class 中)来通过此委托传递我的 XML。查看Jax2Marshaller
源码,发现在方法unmarshalStaxSource(Unmarshaller jaxbUnmarshaller, Source staxSource)
:
XMLStreamReader
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");
}
}
}
所以我的问题是,如何覆盖此方法以添加委托?
您可以使用 2.6+ 版本的 Moxy 来实现不区分大小写的编组。这是针对特定目的进行的特定增强的 link。
您必须将 UNMARSHALLING_CASE_INSENSITIVE
属性 设置为 true。这是一些示例代码
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);