web-dev-qa-db-ja.com

JAXBマーシャリングしながら、名前空間接頭辞を削除します

スキーマから作成されたJAXBオブジェクトがあります。整列化しているときに、XML要素はNS2で注釈を付けてきています。私はこの問題のためにネット上に存在するすべてのオプションを試してみましたが、それらのどれも機能しません。私は自分のスキーマを変更したり、package-info.Javaを変更することはできません。助けてください

21
user2487308

多くの研究といじくり回した後、私はついにこの問題の解決策を達成することができました。オリジナルのリファレンスへのリンクを投稿しないことをおmyび申し上げます-たくさんあり、メモを取っていませんが- 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));

より効率的なメカニズムがあると確信していますが、これが機能することは知っています。

18
OldCurmudgeon

私にとっては、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;
13
cata2d

名前空間を一度だけ書くことができます。 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());

プロキシクラス(重要なメソッドは「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
Amio.io

あなたのユースケースのための名前空間接頭辞を制御するためにNamespacePrefixMapper拡張子を使用することができます。同じ拡張子はJAXBリファレンス実装とのEclipseLink JAXB(MOXY)の両方でサポートされています。

3
bdoughan