2010-05-12 122 views
16

我有一个相当大的重复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产生这样

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

的XML虽然这是一个有效的XML,但它只是看起来很丑,所以我不知道有没有办法告诉编组不要把名字项目元素的空间?或者有没有更好的方法来使用JAXB按块来序列化为XML块?

+0

其实您的实施和建议的输出不匹配。 您正在编写根标签,为什么根元素的输出中有一个名称空间。 – tkr 2010-05-12 11:34:40

+0

啊,很好。因为我实际上使用JAXB来“硬编码”根元素。所以我做的是创建一个空的Root对象,将它编组为String,然后解析String以提取根标记。因此,如果JAXB不为根标记生成名称空间,那么我注定要失败。 – Alvin 2010-05-12 19:42:59

回答

6

以下为我做的伎俩:

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

http://stackoverflow.com/questions/17222902/删除命名空间前缀时,JAXB编组帮我 – 2015-02-21 18:37:50

1

如果您未指定名称空间JaxB将不会写入一个名称空间。

如果你的strcuture不复杂,Yout可以在Stream上使用Stax。

+0

但事实是我需要一个命名空间,但只是在根元素级别。 – Alvin 2010-05-12 08:57:47

11

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

另外,@XmlRootElement注释中有namespace属性。

+0

有没有办法在绑定文件中指定不要将命名空间放入我的package-info.java中,而仅将命名空间放在@XmlRootElement中? – Alvin 2010-05-12 07:33:59

+0

你可以在'@ XmlRootElement'中覆盖它,但据我所知,你希望它完全删除。 – Bozho 2010-05-12 09:28:43

+0

我尝试添加-npa,但由于某种原因它不适用于jaxb2-maven-plugin。我只是想在package-info中将名称空间属性设置为“”。自动生成的java。 我@XmlRootElement具有命名空间=“”,但仍当它被编组它得到的命名空间这是目前在package-info.java。 完整的细节在这里:http://stackoverflow.com/questions/15796063/remove-xmlns-attribute-from-the-root-element-while-marshalling-jaxb – icedek 2013-04-08 17:47:42

6

。在你的情况下,摆脱空间前缀的方式非常简单:只需设置属性将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"> 

我希望这有助于。

问候 帕维尔Procaj

+6

这个伟大的工程,但没有在第一(根)标签摆脱命名空间,以及一种方式? – icedek 2013-04-08 16:46:13

+0

我正在找它!谢谢! – 2014-10-30 09:53:07

1

对于我来说,只是要求xmlStreamWriter.setDefaultNamespace("")解决的问题。

为了从输出中删除名称空间前缀,还需要注意的一点是,无论您拥有@XmlElement,都确保它不包含像@XmlElement(name="", namespace"http://...")这样的名称空间属性;否则,任何解决方案都无法工作。

-2

这个工作对我来说:

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

4

我已经尝试过所有提供的解决方案作为答案在这里,没有人为我的环境工作。我目前的要求是:

  1. jdk1.6。0_45
  2. JAXB注释类在每次重建时都会生成,所以 更改它们不是一个选项。

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

定制NamespaceContextlink

简单而优雅的解决方案,但在我的环境我有以下的堆栈跟踪异常:

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.javalink

我发现最简单的方案的修改。它通常可以工作,但是这个文件是在每次构建时生成的。这就是为什么我必须找到另一种解决方案。

架构修改link

作品所描述的,但并没有解决我的问题。我仍然在根元素中有一个名称空间。

DelegatingXMLStreamWriterlink

我也试着解决方案有提及,但我在com.sun.xml.bind.v2.runtime.output.NamespaceContextImpl(方法declareNsUri),其中我有一个奇怪的断言未能击败。

我的解决方案

虽然与断言研究的问题,我必须实现我自己的基于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版本XMLStreamWriter的。希望这会帮助你节省一些时间来解决类似的问题。

PS。没有必要在代码中扩展DelegatingXMLStreamWriter。我已经完成了这一步,以显示哪些方法需要改变。

+0

这适用于多个命名空间+1的情况 – 2017-01-03 09:42:27