J'ai des objets JAXB créés à partir d'un schéma. Pendant le marshaling, les éléments xml sont annotés avec ns2. J'ai essayé toutes les options qui existent sur le net pour ce problème, mais aucune ne fonctionne. Je ne peux pas modifier mon schéma ou changer package-info.Java. Veuillez aider
Après beaucoup de recherches et de bricolage, j'ai finalement réussi à trouver une solution à ce problème. Veuillez accepter mes excuses pour ne pas avoir publié de liens vers les références originales - il y en a beaucoup et je ne prenais pas de notes - mais this one était certainement utile.
Ma solution utilise un filtrage XMLStreamWriter
qui applique un contexte d'espace de noms vide.
public class NoNamesWriter extends DelegatingXMLStreamWriter {
private static final NamespaceContext emptyNamespaceContext = new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
return "";
}
@Override
public String getPrefix(String namespaceURI) {
return "";
}
@Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
};
public static XMLStreamWriter filter(Writer writer) throws XMLStreamException {
return new NoNamesWriter(XMLOutputFactory.newInstance().createXMLStreamWriter(writer));
}
public NoNamesWriter(XMLStreamWriter writer) {
super(writer);
}
@Override
public NamespaceContext getNamespaceContext() {
return emptyNamespaceContext;
}
}
Vous pouvez trouver un DelegatingXMLStreamWriter
ici .
Vous pouvez ensuite filtrer le XML de marshaling avec:
// Filter the output to remove namespaces.
m.marshal(it, NoNamesWriter.filter(writer));
Je suis sûr qu'il existe des mécanismes plus efficaces mais je sais que celui-ci fonctionne.
Pour moi, changer uniquement la classe package-info.Java a fonctionné comme un charme, exactement comme l'a déclaré zatziky:
package-info.Java
@javax.xml.bind.annotation.XmlSchema
(namespace = "http://example.com",
xmlns = {@XmlNs(prefix = "", namespaceURI = "http://example.com")},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package my.package;
import javax.xml.bind.annotation.XmlNs;
Vous ne pouvez laisser les espaces de noms écrits qu'une seule fois. Vous aurez besoin d'une classe proxy de XMLStreamWriter et d'un package-info.Java. Ensuite, vous ferez dans votre code:
StringWriter stringWriter = new StringWriter();
XMLStreamWriter writer = new Wrapper((XMLStreamWriter) XMLOutputFactory
.newInstance().createXMLStreamWriter(stringWriter));
JAXBContext jaxbContext = JAXBContext.newInstance(Collection.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
jaxbMarshaller.marshal(books, writer);
System.out.println(stringWriter.toString());
Classe proxy (la méthode importante est "writeNamespace"):
class WrapperXMLStreamWriter implements XMLStreamWriter {
private final XMLStreamWriter writer;
public WrapperXMLStreamWriter(XMLStreamWriter writer) {
this.writer = writer;
}
//keeps track of what namespaces were used so that not to
//write them more than once
private List<String> namespaces = new ArrayList<String>();
public void init(){
namespaces.clear();
}
public void writeStartElement(String localName) throws XMLStreamException {
init();
writer.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
init();
writer.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
init();
writer.writeStartElement(prefix, localName, namespaceURI);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
if(namespaces.contains(namespaceURI)){
return;
}
namespaces.add(namespaceURI);
writer.writeNamespace(prefix, namespaceURI);
}
// .. other delegation method, always the same pattern: writer.method() ...
}
package-info.Java:
@XmlSchema(elementFormDefault=XmlNsForm.QUALIFIED, attributeFormDefault=XmlNsForm.UNQUALIFIED ,
xmlns = {
@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")})
package your.package;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Vous pouvez utiliser l'extension NamespacePrefixMapper
pour contrôler les préfixes d'espace de noms pour votre cas d'utilisation. La même extension est prise en charge à la fois par l'implémentation de référence JAXB et par EclipseLink JAXB (MOXy).