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

17
demandé sur user2487308 2013-06-21 00:12:09

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 DelegatingXMLStreamWriterici.

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.

14
répondu OldCurmudgeon 2017-05-23 11:33:13

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;
12
répondu cata2d 2015-10-23 08:11:26

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;
5
répondu zatziky 2016-06-15 00:55:31

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).

2
répondu Blaise Doughan 2013-06-20 20:44:32

je suis le travail de résultat par la définition de la propriété:

marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");
-2
répondu App Work 2016-06-15 01:00:28