Supprimer le préfixe namespace pendant que JAXB marshalling
j'ai des objets JAXB créés à partir d'un schéma. Pendant la formation, 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 aucun d'entre eux travaille. Je ne peux pas modifier mon schéma ou changer les informations du paquet.Java. S'il vous plaît aider
5 réponses
après beaucoup de recherches et de bricolages, j'ai finalement réussi à trouver une solution à ce problème. Veuillez accepter mes excuses pour ne pas avoir affiché de liens vers les références originales - il y en a beaucoup et je ne prenais pas de notes - mais est 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 alors filtrer sérialisation xml:
// 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, je change seulement le paquet-info.java class a fonctionné comme un charme, exactement comme zatziky a déclaré:
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 pouvez laisser les namespaces être écrits qu'une seule fois. Vous aurez besoin d'une classe proxy de XMLStreamWriter et d'un paquet-info.Java. Ensuite, vous allez faire 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 le NamespacePrefixMapper
extension de contrôler les préfixes d'espace de noms pour votre cas d'utilisation. La même extension est supportée à la fois par L'implémentation de référence JAXB et par EclipseLink JAXB (MOXy).
je suis le travail de résultat par la définition de la propriété:
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");