Я перепробовал все решения, представленные здесь, и ни одно из них не подошло для моей среды Мои текущие требования:
- jdk1.6.0_45
- JAXB-аннотированные классы генерируются при каждой перестройке, поэтому
изменять их нельзя.
Я хотел бы поделиться с вами результатами моих экспериментов с решениями, которые я нашел в stackoverflow.
Пользовательский NamespaceContext ссылка
Простое и элегантное решение, но в моей среде у меня есть исключение со следующей трассировкой стека:
javax.xml.stream.XMLStreamException: Trying to write END_DOCUMENT when document has no root (ie. trying to output empty document).
at com.ctc.wstx.sw.BaseStreamWriter.throwOutputError(BaseStreamWriter.java:1473)
at com.ctc.wstx.sw.BaseStreamWriter.reportNwfStructure(BaseStreamWriter.java:1502)
at com.ctc.wstx.sw.BaseStreamWriter.finishDocument(BaseStreamWriter.java:1663)
at com.ctc.wstx.sw.BaseStreamWriter.close(BaseStreamWriter.java:288)
at MyDataConverter.marshal(MyDataConverter.java:53)
Я застрял, пытаясь выяснить причину возникновения этого исключения, и решил попробовать что-то еще.
Модификация package-info.java ссылка
Самое простое решение, которое я нашел. Обычно это работает, но этот файл создается при каждой сборке. Вот почему я должен найти другое решение.
Модификация схемы ссылка
Работает как описано, но не решает мою проблему. У меня все еще есть пространство имен в корневом элементе.
DelegatingXMLStreamWriter ссылка
Я также пробовал решения, упомянутые там, но у меня было странное утверждение в com.sun.xml.bind.v2.runtime.output.NamespaceContextImpl (метод DeclareNsUri), который я не смог победить.
Мое решение
При изучении проблемы с утверждением мне пришлось реализовать собственную версию XMLStreamWriter на основе DelegatingXMLStreamWriter.java
public class NamespaceStrippingXMLStreamWriter extends DelegatingXMLStreamWriter {
public NamespaceStrippingXMLStreamWriter(XMLStreamWriter xmlWriter) throws XMLStreamException {
super(xmlWriter);
}
@Override
public void writeNamespace(String prefix, String uri) throws XMLStreamException {
// intentionally doing nothing
}
@Override
public void writeDefaultNamespace(String uri) throws XMLStreamException {
// intentionally doing nothing
}
@Override
public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
super.writeStartElement(null, local, null);
}
@Override
public void writeStartElement(String uri, String local) throws XMLStreamException {
super.writeStartElement(null, local);
}
@Override
public void writeEmptyElement(String uri, String local) throws XMLStreamException {
super.writeEmptyElement(null, local);
}
@Override
public void writeEmptyElement(String prefix, String local, String uri) throws XMLStreamException {
super.writeEmptyElement(null, local, null);
}
@Override
public void writeAttribute(String prefix, String uri, String local, String value) throws XMLStreamException {
super.writeAttribute(null, null, local, value);
}
@Override
public void writeAttribute(String uri, String local, String value) throws XMLStreamException {
super.writeAttribute(null, local, value);
}
}
Основная идея состоит в том, чтобы избежать передачи информации о пространстве имен в базовый XMLStreamWriter. Надеюсь, это поможет вам сэкономить время на решение аналогичной проблемы.
PS. Нет необходимости расширять DelegatingXMLStreamWriter в вашем коде. Я сделал это, чтобы показать, какие методы нужно изменить.