Java 如何在没有命名空间的情况下编组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2816176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:11:32  来源:igfitidea点击:

How to marshal without a namespace?

javaxmljaxb

提问by Alvin

I have a fairly large repetitive XML to create using JAXB. Storing the whole object in the memory then do the marshaling takes too much memory. Essentially, my XML looks like this:

我有一个相当大的重复 XML 使用 JAXB 创建。将整个对象存储在内存中然后进行编组需要太多内存。本质上,我的 XML 如下所示:

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

Currently my solution to the problem is to "hard code" the root tag to an output stream, and marshal each of the repetitive element one by one:

目前我对这个问题的解决方案是将根标签“硬编码”到一个输出流中,并一个一个地编组每个重复元素:

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

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

Somehow the JAXB generate the XML like this

JAXB 以某种方式生成这样的 XML

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

Although this is a valid XML, but it just looks ugly, so I'm wondering is there any way to tell the marshaller not to put namespace for the item elements? Or is there better way to use JAXB to serialize to XML chunk by chunk?

虽然这是一个有效的 XML,但它看起来很难看,所以我想知道有什么方法可以告诉编组器不要为 item 元素放置命名空间?或者是否有更好的方法使用 JAXB 逐块序列化为 XML?

采纳答案by Tamas Kornai

The following did the trick for me:

以下对我有用:

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

回答by tkr

If you don't specifiy a namespace JaxB will not write one.

如果您不指定命名空间,JaxB 将不会编写一个。

Yout could use Stax on a Stream, if your strcuture is not to complicated.

如果您的结构不是很复杂,您可以在 Stream 上使用 Stax。

回答by Bozho

Check your package-info.java(in the package where your jaxb-annotated classes are). There is the namespaceattribute of @XmlSchemathere.

检查您的package-info.java(在您的 jaxb 注释类所在的包中)。有那里的namespace属性@XmlSchema

Also, there is a namespaceattribute in the @XmlRootElementannotation.

此外,注释中有一个namespace属性 @XmlRootElement

回答by MrShinobi

There is a very simple way to get rid of namespace prefixes in your case: just set the attribute elementFormDefaultto unqualifiedin your schema, like this:

在您的情况下,有一种非常简单的方法可以摆脱命名空间前缀:只需在您的架构中将属性elementFormDefault设置为unqualified,如下所示:

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

You will get the namespace prefix only in the first tag:

您将仅在第一个标签中获得命名空间前缀:

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

I hope this helps.

我希望这有帮助。

Regards Pawel Procaj

问候 Pawel Procaj

回答by HamedKhan

For me, simply calling xmlStreamWriter.setDefaultNamespace("")solved the issue.

对我来说,只需调用即可xmlStreamWriter.setDefaultNamespace("")解决问题。

One more thing you have to care in order to remove the namespace prefix from the output is that everywhere you have @XmlElement ensure it does not include the namespace property like @XmlElement(name="", namespace"http://..."); otherwise, none of solutions will work.

为了从输出中删除名称空间前缀,您还需要注意的另一件事是,在您拥有 @XmlElement 的任何地方确保它不包含名称空间属性,例如@XmlElement(name="", namespace"http://...");否则,任何解决方案都不会奏效。

回答by App Work

This works for me:

这对我有用:

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

marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,“”);

回答by sergio

I've tried all solutions provided as answers here and none of them worked for my environment. My current requirements are:

我已经尝试了此处作为答案提供的所有解决方案,但没有一个适用于我的环境。我目前的要求是:

  1. jdk1.6.0_45
  2. JAXB annotated classes are generated upon every rebuild, so changing them is not an option.
  1. jdk1.6.0_45
  2. JAXB 注释类在每次重建时生成,因此更改它们不是一种选择。

I'd like to share with you the results my experiments with solutions I've found on stackoverflow.

我想与您分享我在 stackoverflow 上找到的解决方案的实验结果。

Custom NamespaceContextlink

自定义命名空间上下文链接

Simple and elegant solution, but in my environment I have an exception with the following 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)

I got stuck trying to figure out why this exception occurs and decided to try out something else.

我在试图弄清楚为什么会发生此异常时陷入困境,并决定尝试其他方法。

Modification of package-info.javalink

修改 package-info.java链接

The simplest solution I've found. It generally works, but this file is generated upon every build. That's why I have to find another solution.

我找到的最简单的解决方案。它通常有效,但此文件是在每次构建时生成的。这就是为什么我必须找到另一个解决方案。

Schema modificationlink

架构修改链接

Works as described but doesn't solve my problem. I still have a namespace in root element.

按描述工作,但不能解决我的问题。我在根元素中仍然有一个命名空间。

DelegatingXMLStreamWriterlink

委托 XMLStreamWriter链接

I've also tried solutions mentioned there, but I had a strange assertion in com.sun.xml.bind.v2.runtime.output.NamespaceContextImpl (method declareNsUri) which I've failed to defeat.

我也尝试过那里提到的解决方案,但我在 com.sun.xml.bind.v2.runtime.output.NamespaceContextImpl(方法declareNsUri)中有一个奇怪的断言,我没能打败它。

My solution

我的解决方案

While researching the issue with assertion I had to implement my own version of XMLStreamWriter based on DelegatingXMLStreamWriter.java

在研究断言问题时,我必须基于DelegatingXMLStreamWriter.java实现我自己的 XMLStreamWriter 版本

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

The main idea is to avoid passing namespace information to the underlying XMLStreamWriter. Hope this will help you to save some time solving similar problem.

主要思想是避免将名称空间信息传递给底层 XMLStreamWriter。希望这将帮助您节省一些时间来解决类似的问题。

PS. It's not necessary to extend DelegatingXMLStreamWriter in your code. I've done this to show which methods need changing.

附注。没有必要在您的代码中扩展 DelegatingXMLStreamWriter。我这样做是为了展示哪些方法需要改变。