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

时间:2010-05-12 05:02:59

标签: java xml jaxb

我使用JAXB创建了一个相当大的重复XML。将整个对象存储在内存中然后进行编组会占用太多内存。基本上,我的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块?

7 个答案:

答案 0 :(得分:12)

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

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

答案 1 :(得分:8)

以下为我做了诀窍:

         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 :(得分: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">

我希望这会有所帮助。

此致 Pawel Procaj

答案 3 :(得分:6)

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

  1. jdk1.6.0_45
  2. 每次重建时都会生成JAXB注释类,所以 改变它们不是一种选择。
  3. 我想与您分享我在stackoverflow上找到的解决方案的实验结果。

    自定义NamespaceContext link

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

    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 link

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

    架构修改 link

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

    DelegatingXMLStreamWriter link

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

    我的解决方案

    在使用断言研究问题时,我必须基于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);
      }
    }
    

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

    PS。没有必要在代码中扩展DelegatingXMLStreamWriter。我这样做是为了说明哪些方法需要改变。

答案 4 :(得分:2)

对我而言,只需致电xmlStreamWriter.setDefaultNamespace("")即可解决问题。

为了从输出中删除命名空间前缀,您还需要注意的是,无论您拥有哪个@XmlElement,都要确保它不包含@XmlElement(name="", namespace"http://...")之类的命名空间属性;否则,没有任何解决方案可行。

答案 5 :(得分:0)

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

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

答案 6 :(得分:-3)

这对我有用:

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