Подтвердить что ты не робот

Как маршалировать без пространства имен?

У меня есть довольно большой повторяющийся XML для создания с использованием JAXB. Сохраняя весь объект в памяти, тогда маршалинг занимает слишком много памяти. По сути, мой XML выглядит следующим образом:

<Store>
  <item />
  <item />
  <item />
.....
</Store>

В настоящее время мое решение проблемы состоит в том, чтобы "жестко закодировать" корневой тег в выходной поток и маршалировать каждый из повторяющихся элементов один за другим:

aOutputStream.write("<?xml version="1.0"?>")
aOutputStream.write("<Store>")

foreach items as item
  aMarshaller.marshall(item, aOutputStream)
end
aOutputStream.write("</Store>")
aOutputStream.close()

Как-то JAXB генерирует такой XML

 <Store  xmlns="http://stackoverflow.com">
  <item xmlns="http://stackoverflow.com"/>
  <item xmlns="http://stackoverflow.com"/>
  <item xmlns="http://stackoverflow.com"/>
.....
</Store>

Хотя это допустимый XML, но он просто выглядит уродливым, так что мне интересно, есть ли способ сказать маршаллеру не помещать пространство имен для элементов элемента? Или есть лучший способ использовать JAXB для сериализации XML-фрагмента куском?

4b9b3361

Ответ 1

Следующее сделало трюк для меня:

         XMLStreamWriter writer = ...
         writer.setNamespaceContext(new NamespaceContext() {
            public Iterator getPrefixes(String namespaceURI) {
                return null;
            }

            public String getPrefix(String namespaceURI) {
                return "";
            }

            public String getNamespaceURI(String prefix) {
                return null;
            }
        });

Ответ 2

Проверьте package-info.java (в пакете, где находятся ваши jaxb-аннотированные классы). Существует атрибут namespace @XmlSchema.

Кроме того, в анноте @XmlRootElement есть атрибут namespace.

Ответ 3

Существует очень простой способ избавиться от префиксов пространства имен в вашем случае: просто установите атрибут elementFormDefault в неквалифицированный в вашей схеме, например:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:your="http://www.stackoverflow.com/your/namespace">

Вы получите префикс пространства имен только в первом теге:

<ns1:your xmlns:ns1="http://www.stackoverflow.com/your/namespace">

Надеюсь, это поможет.

Отношения Pawel Procaj

Ответ 4

Я пробовал все решения, предоставленные в качестве ответов здесь, и никто из них не работал в моей среде. Мои текущие требования:

  • jdk1.6.0_45
  • Якорные классы JAXB генерируются при каждом восстановлении, поэтому изменение их не является вариантом.

Я хотел бы поделиться с вами результатами моих экспериментов с решениями, которые я нашел в stackoverflow.

Пользовательское пространство именContext

Простое и элегантное решение, но в моей среде у меня есть исключение со следующей командой stacktrace:

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 в вашем коде. Я сделал это, чтобы показать, какие методы необходимо изменить.

Ответ 5

Если вы не указали пространство имен, JaxB не будет писать его.

Yout может использовать Stax в потоке, если ваш strcuture не усложняется.

Ответ 6

Для меня просто вызов xmlStreamWriter.setDefaultNamespace("") решил проблему.

Еще одна вещь, которую вы должны заботиться, чтобы удалить префикс пространства имен из вывода, - это то, что везде, где вы @XmlElement, он не включает свойство пространства имен, например @XmlElement(name="", namespace"http://..."); в противном случае ни один из решений не будет работать.

Ответ 7

Это работает для меня:

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