Ich benutze Jaxb2 und Spring. Ich versuche, XML zu entpacken, das von zwei meiner Kunden gesendet wird.Jaxb ignorieren den Namespace auf Unmarshalling
Bisher hatte ich nur einen Kunden zu handhaben, die einige xml wie folgt gesendet:
<foo xmlns="com.acme">
<bar>[...]</bar>
<foo>
, die zu einem POJO wie diese gebunden ist:
@XmlType(name = "", propOrder = {"bar"})
@XmlRootElement(name = "Foo")
public class Foo {
@XmlElement(name = "Bar")
private String bar;
[...]
}
Ich entdeckte, dass die vorherige Der Entwickler hat den Namensraum im Unmarshaller fest programmiert, damit er funktioniert.
Jetzt sendet der zweite Kunde das gleiche XML, ändert jedoch den Namespace!
<foo xmlns="com.xyz">
<bar>[...]</bar>
<foo>
Offensichtlich schlägt die Unmarshaller entordnen, weil es einige {com.acme}foo
statt {com.xyz}foo
erwartet. Leider ist es nicht möglich, den Kunden zu bitten, das XML zu ändern.
Was ich versucht:
1) In application-context.xml
, ich für eine Konfiguration gesucht, die mir erlauben würde, den Namensraum zu ignorieren, aber nicht finden konnte:
<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>
es scheint, dass Die einzigen verfügbaren Optionen sind diejenigen, die im Javadoc von Jaxb2Marshaller aufgeführt sind:
/**
* 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) Ich habe auch versucht die Unmarshaller im Code zu konfigurieren:
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) Verschiedene Form mit einem 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(...) {[...]}
Dieser funktioniert! Aber trotzdem würde ich lieber den Unmarshaller autowire machen können, ohne dieses hässliche conf jedes Mal zu benötigen.