У меня есть объекты JAXB, созданные из схемы. При сортировке элементов xml аннотируются с помощью ns2. Я пробовал все варианты, которые существуют по сети для этой проблемы, но никто из них не работает. Я не могу изменить мою схему или изменить package-info.java. Пожалуйста, помогитеУдалить префикс пространства имен при сортировке JAXB
ответ
После долгих исследований и мастерить я, наконец, удалось добиться решения этой проблемы. Примите мои извинения за то, что вы не публикуете ссылки на оригинальные ссылки - их много, и я не делал заметок, но 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;
}
}
Вы можете найти DelegatingXMLStreamWriter
here.
Вы можете фильтровать сортировочной XML с:
// Filter the output to remove namespaces.
m.marshal(it, NoNamesWriter.filter(writer));
Я уверен, что есть более эффективные механизмы, но я знаю, что это работает.
в случае, если вы не хотите использовать CXF, импортировать JAXWS-rtxxx .jar, то с использованием стандартного jawx-ws делает тот же трюк по коду: class NoNamesWriter расширяет XMLStreamWriterFilter, –
Вы можете использовать расширение NamespacePrefixMapper
для управления префиксами пространства имен для вашего прецедента. Такое же расширение поддерживается как эталонной реализацией JAXB, так и EclipseLink JAXB (MOXy).
Вы можете позволить пространствам имен писать только один раз. Вам понадобится прокси-класс 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;
Я получил рабочий результат путем установления свойства:
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");
Для меня, только изменив класс 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;
Al три года спустя также работает как шарм. – fdam
Другое решение упомянутых здесь [http://stackoverflow.com/а/29945934/4745777] [1] [1]: http://stackoverflow.com/a/29945934/4745777 – HamedKhan