2013-06-20 4 views
13

У меня есть объекты JAXB, созданные из схемы. При сортировке элементов xml аннотируются с помощью ns2. Я пробовал все варианты, которые существуют по сети для этой проблемы, но никто из них не работает. Я не могу изменить мою схему или изменить package-info.java. Пожалуйста, помогитеУдалить префикс пространства имен при сортировке JAXB

+0

Другое решение упомянутых здесь [http://stackoverflow.com/а/29945934/4745777] [1] [1]: http://stackoverflow.com/a/29945934/4745777 – HamedKhan

ответ

11

После долгих исследований и мастерить я, наконец, удалось добиться решения этой проблемы. Примите мои извинения за то, что вы не публикуете ссылки на оригинальные ссылки - их много, и я не делал заметок, но this один был, безусловно, полезен.

Мое решение использует фильтрацию XMLStreamWriter, которая применяет пустой контекст пространства имен.

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; 
    } 

} 

Вы можете найти DelegatingXMLStreamWriterhere.

Вы можете фильтровать сортировочной XML с:

// Filter the output to remove namespaces. 
    m.marshal(it, NoNamesWriter.filter(writer)); 

Я уверен, что есть более эффективные механизмы, но я знаю, что это работает.

+3

в случае, если вы не хотите использовать CXF, импортировать JAXWS-rtxxx .jar, то с использованием стандартного jawx-ws делает тот же трюк по коду: class NoNamesWriter расширяет XMLStreamWriterFilter, –

4

Вы можете позволить пространствам имен писать только один раз. Вам понадобится прокси-класс XMLStreamWriter и package-info.java. Тогда вы будете делать в вашем коде:

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()); 

класс Proxy (важный метод "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; 
0

Я получил рабочий результат путем установления свойства:

marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, ""); 
8

Для меня, только изменив класс package-info.java работал как шарм, точно так, как указано 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; 
+0

Al три года спустя также работает как шарм. – fdam