Używam Jaxb2 i Spring. Próbuję anulować niektóre XML, które są wysyłane przez 2 moich klientów.Jaxb ignoruje przestrzeń nazw w unmarshalling
Do tej pory miałem tylko do obsługi jednego klienta, który wysłał kilka xml jak poniżej:
<foo xmlns="com.acme">
<bar>[...]</bar>
<foo>
, który jest związany z POJO tak:
@XmlType(name = "", propOrder = {"bar"})
@XmlRootElement(name = "Foo")
public class Foo {
@XmlElement(name = "Bar")
private String bar;
[...]
}
odkryłem, że poprzedni programista zakodował przestrzeń nazw w unmarshallerze, aby działał.
Teraz drugi klient wysyła ten sam plik XML, ale zmienia przestrzeń nazw!
<foo xmlns="com.xyz">
<bar>[...]</bar>
<foo>
Oczywiście unmarshaller nie wycofać, ponieważ spodziewa się {com.acme}foo
zamiast {com.xyz}foo
. Niestety, prośba klienta o zmianę kodu XML nie jest możliwa.
Co próbowałem:
1) W application-context.xml
, szukałem dla konfiguracji, która pozwoliłaby mi się ignorować nazw, ale nie mógł znaleźć jednego:
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="packagesToScan">
<list>
<value>com.mycompany.mypkg</value>
</list>
</property>
<property name="marshallerProperties">
<map>
<entry key="???"><value type="java.lang.Boolean">false</value></entry>
</map>
</property>
</bean>
wydaje się, że jedynymi dostępnymi opcjami są te wymienione w Javadoc Jaxb2Marshaller:
/**
* Set the JAXB {@code Marshaller} properties. These properties will be set on the
* underlying JAXB {@code Marshaller}, and allow for features such as indentation.
* @param properties the properties
* @see javax.xml.bind.Marshaller#setProperty(String, Object)
* @see javax.xml.bind.Marshaller#JAXB_ENCODING
* @see javax.xml.bind.Marshaller#JAXB_FORMATTED_OUTPUT
* @see javax.xml.bind.Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION
* @see javax.xml.bind.Marshaller#JAXB_SCHEMA_LOCATION
*/
public void setMarshallerProperties(Map<String, ?> properties) {
this.marshallerProperties = properties;
}
2) Próbowałem też skonfigurować unmarshaller w kodzie:
try {
jc = JAXBContext.newInstance("com.mycompany.mypkg");
Unmarshaller u = jc.createUnmarshaller();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(false);//Tried this option.
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(xmlFile.toFile());
u.unmarshal(new DOMSource(doc));
return (Foo)u.unmarshal(new StreamSource(xmlFile.toFile()));
} catch (ParserConfigurationException | SAXException | IOException | JAXBException e) {
LOGGER.error("Erreur Unmarshalling CPL");
}
3) innej formie z SAXParser:
try {
jc = JAXBContext.newInstance("com.mycompany.mypkg");
Unmarshaller um = jc.createUnmarshaller();
final SAXParserFactory sax = SAXParserFactory.newInstance();
sax.setNamespaceAware(false);
final XMLReader reader = sax.newSAXParser().getXMLReader();
final Source er = new SAXSource(reader, new InputSource(new FileReader(xmlFile.toFile())));
return (Foo)um.unmarshal(er);
}catch(...) {[...]}
Ten działa! Ale nadal wolałbym móc wyposażyć Unmarshallera bez potrzeby brzydkiego conf za każdym razem.