2010-05-12 15 views
16

Tengo un XML repetitivo bastante grande para crear usando JAXB. Almacenar todo el objeto en la memoria y hacer el cálculo de referencias requiere demasiada memoria. En esencia, mi XML tiene el siguiente aspecto:¿Cómo conseguir un espacio de nombres sin un nombre?

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

Actualmente mi solución al problema es "codificar" la etiqueta raíz de un flujo de salida, y el mariscal cada uno de los elemento repetitivo uno por uno:

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

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

de alguna manera el JAXB generar el XML como esto

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

Aunque este es un XML válido, pero que sólo se ve feo, así que me pregunto ¿hay alguna manera de saber el contador de referencias de no poner el nombre espacio para los elementos del elemento? ¿O hay una mejor manera de usar JAXB para serializar en fragmentos de XML por fragmentos?

+0

En realidad, su implementación y la salida sugerida no coinciden. Usted está escribiendo la etiqueta raíz usted mismo, por qué hay un espacio de nombres en el resultado en el elemento raíz. – tkr

+0

Ahh buena captura. Porque realmente uso JAXB para "codificar" el elemento raíz también. Entonces, lo que hice fue crear un objeto Root vacío, dirigirlo a una Cadena, luego analizar la Cadena para extraer las etiquetas raíz. Entonces, si JAXB no genera espacio de nombres para la etiqueta raíz, entonces estoy condenado. – Alvin

Respuesta

6

A continuación se hizo el truco para mí:

  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/ remove-namespace-prefix-while-jaxb-marshalling me ayudó –

1

Si no especifica un espacio de nombres, JaxB no escribirá uno.

Yout podría usar Stax en un Stream, si su strcution no es complicado.

+0

pero el hecho es que necesito un espacio de nombres, pero solo en el nivel del elemento raíz. – Alvin

11

Compruebe su package-info.java (en el paquete donde están sus clases con anotaciones jaxb). Existe el atributo namespace de @XmlSchema allí. También hay un atributo namespace en la anotación @XmlRootElement.

+0

¿Hay alguna manera de especificar en el archivo de enlace no poner espacio de nombres en mi package-info.java y solo poner el espacio de nombres en @XmlRootElement? – Alvin

+0

puede anularlo en '@ XmlRootElement', pero por lo que yo entiendo, quiere que se elimine por completo. – Bozho

+0

Intenté agregar el -npa pero no funcionará en jaxb2-maven-plugin por algún motivo. Solo quiero hacer que el atributo de espacio de nombres sea "" en la información del paquete.Java que se genera automáticamente. Mi @XmlRootElement tiene namespace = "" pero aun así, cuando se organiza, obtiene el espacio de nombres que está presente en package-info.java. Detalles completos aquí: http://stackoverflow.com/questions/15796063/remove-xmlns-attribute-from-the-root-element-while-marshalling-jaxb – icedek

6

Hay una forma muy sencilla de deshacerse de los prefijos de espacio de nombres en su caso: acaba de establecer el atributo elementFormDefault a sin reservas en su esquema, de esta manera:

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

obtendrá el prefijo de espacio de nombres sólo en la primera etiqueta:

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

Espero que esto ayude.

Saludos Pawel Procaj

+6

Esto funciona muy bien, pero ¿hay alguna manera de deshacerse del espacio de nombres en la primera etiqueta (raíz) también? – icedek

+0

¡Lo estaba buscando! ¡Gracias! –

1

Para mí, simplemente llamando xmlStreamWriter.setDefaultNamespace("") resolvió el problema.

Una cosa más que debe tener cuidado para eliminar el prefijo del espacio de nombres del resultado es que en todos los lugares que tenga @XmlElement asegúrese de que no incluya la propiedad del espacio de nombres como @XmlElement(name="", namespace"http://..."); de lo contrario, ninguna de las soluciones funcionará.

-2

Esto funciona para mí:

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

4

He intentado todas las soluciones proporcionadas como respuestas aquí y ninguna de ellas funcionó para mi entorno. Mis requisitos actuales son:

  1. jdk1.6.0_45
  2. JAXB las clases anotadas se generan en cada reconstrucción, por lo que cambiarlas no es una opción.

Me gustaría compartir con ustedes los resultados de mis experimentos con las soluciones que he encontrado en stackoverflow.

NamespaceContext personalizadalink

solución simple y elegante, pero en mi entorno tengo una excepción con el siguiente 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) 

me quedé atrapado tratando de averiguar por qué se produce esta excepción y Decidí probar algo más.

Modificación de package-info.javalink

La solución más sencilla que he encontrado. En general, funciona, pero este archivo se genera en cada compilación. Es por eso que tengo que encontrar otra solución.

modificación del esquemalink

Obras como se describe, pero no resuelve mi problema. Todavía tengo un espacio de nombres en el elemento raíz.

DelegatingXMLStreamWriterlink

También he intentado soluciones mencionadas allí, pero tenía una extraña afirmación en com.sun.xml.bind.v2.runtime.output.NamespaceContextImpl (método declareNsUri), que yo' No he podido vencer.

Mi solución

Durante la investigación de la cuestión con la afirmación que tuvo que poner en práctica mi propia versión de XMLStreamWriter basado en 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); 
    } 
} 

La idea principal es evitar la transmisión de información de espacio de nombres a la XMLStreamWriter subyacente . Espero que esto te ayude a ahorrar algo de tiempo para resolver un problema similar.

PS. No es necesario extender DelegatingXMLStreamWriter en su código. Hice esto para mostrar qué métodos necesitan cambios.

+0

Esto funciona bien en caso de múltiples espacios de nombres +1 –

Cuestiones relacionadas