2011-10-28 13 views
6

Tengo un XSD que no se crea por sí mismo, sino que se recibe de otra persona. Así que no puedo cambiar este XSD porque debo asegurar la comptibilidad con la otra parte.Cómo evitar declaraciones de espacio de nombres innecesarias en un elemento/etiqueta ordenada?

Usando XJC 2.2 y JAXB 2.2 usando el modo de unión sencilla Quiero crear un elemento raíz con el interior de un elemento de hola vacía. Pero cuando me reúnen, recibo mucha basura adicional del espacio de nombres. Lo cual para mí parece innecesario. (Funciona sin embargo, pero es más datos para enviar ect ...)

XSD rootElement:

código
<element name="epp"> 
     <complexType> 
      <choice> 
       <element name="greeting" type="epp:greetingType" /> 
       <element name="hello" /> 
       <element name="command" type="epp:commandType" /> 
       <element name="response" type="epp:responseType" /> 
       <element name="extension" type="epp:extAnyType" /> 
      </choice> 
     </complexType> 
    </element> 

Java:

Epp epp = new Epp(); 
epp.setHello(""); 

Resultado marshalled:

<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"> 
    <hello xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string"></hello> 
</epp> 

Resultado preferido:

<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"> 
<hello /> 
</epp> 

O:

<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"> 
<hello></hello> 
</epp> 

¿Hay alguna manera de hacer que esto sea posible, preferiblemente sin cambiar XSD o manualmente cambiar clases compiladas el xjc?

+1

importa si puedo editar el título de la pregunta? Se siente como si estuvieras preguntando cómo generar un elemento sin contenido, pero eso se solucionó. El objetivo real es evitar las declaraciones superfluas del espacio de nombres. –

+0

No hay problema, es mi primera pregunta aquí ... :), Sí, el objetivo es deshacerse de esas decs del espacio de nombres –

+0

¿Intentó no establecer el valor Hello (no se ejecuta epp.setHello (""))? – altanis

Respuesta

4

El problema es el siguiente: el esquema no define un tipo de elemento de hello. Como resultado, XJC genera un campo con tipo Object. Eso significa que JAXB debe detectar, durante la clasificación, con qué tipo de objeto estamos tratando. No estoy seguro de los detalles, pero supongo que comprobará el tipo de tiempo de ejecución y luego se ocupará de ello en consecuencia. Desde String - que es lo que realmente pone en el campo hello - tiene una unión directa a un tipo de esquema (es decir, xs:string) JAXB se va a ir con eso. Hasta aquí todo bien.

Pero JAXB trata de generar XML que va a ser útil para unmarshalling también. Debido a que el esquema no especificaba un tipo y el campo hello es un Objeto, intentar desarticular de XML dejaría a JAXB adivinando en qué debería realmente convertir el contenido. Una forma de indicarle cómo se especifica el tipo en el elemento XML, utilizando el atributo xsi:type. Este atributo se encuentra dentro del espacio de nombres de xsi -bound, por lo que ese prefijo debe declararse y vincularse. Eso es lo que sucede con xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance". Pero eso no es todo ... El xsi:type declarado hace uso de un tipo en el espacio de nombres del Esquema XML, ligado al prefijo xs, lo que significa que también debe declararse ESO. De ahí el xmlns:xs="http://www.w3.org/2001/XMLSchema".

El resultado: un lío de declaraciones de espacios sólo para decirle a quien utiliza el XML que lo hace, de hecho, contiene una cadena. Esto podría resolverse agregando cadena como el tipo para el elemento hola en el esquema, pero esa no es una opción para usted.

Afortunadamente, usted no está totalmente fuera de suerte. Puede personalizar enlaces utilizando un archivo de enlaces externo. Los detalles se pueden encontrar aquí: http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html

Normalmente, este archivo de enlaces debe hacer el truco:

<?xml version="1.0" encoding="UTF-8"?> 
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd" 
    version="2.1"> 

    <!-- Bindings for the general schema --> 
    <bindings schemaLocation="test.xsd" node="/xs:schema"> 

     <bindings node="xs:element[@name='epp']"> 
      <bindings node=".//xs:element[@name='hello']"> 
       <javaType name="java.lang.String" /> 
      </bindings> 
     </bindings> 

    </bindings> 

</bindings> 

... pero cuando intento xjc con esto que estoy recibiendo el error the compiler was unable to honor this javaType customization.Funciona cuando especifico un tipo de esquema estándar (como string o int) en el elemento hello en el esquema, pero tampoco funcionó cuando traté de proporcionar métodos de análisis e impresión para la conversión, así que voy a tener asumir que esto es un error en xjc que ocurre cuando no se especifica ningún tipo en el esquema.

Espero que alguien más pueda dar consejos sobre el problema de las vinculaciones. De lo contrario, la única opción que veo es enviar su esquema a través de alguna transformación XSLT antes de desencadenar XJC en él para configurar cada elemento no tipado en cadena de forma predeterminada.

+0

Intenté esto pero desafortunadamente recibo los mismos errores ... Mientras estoy usando 'epp.setHello (" ");' para que el marshaller sepa que debe dar salida al elemento. Quizás haya otra forma de configurar el elemento hola que no genera una cadena. Dado que XJC compila la función como un 'void público setHello (Valor del objeto)' usando null es como no configurarlo y no será recogido por el Marshaller. Para hacer una suposición "estúpida", ¿hay un objeto JAXB "nulo"? :) –

+0

@PhoenixtheII ¿Usaste el archivo de enlaces? Si es así, ¿funcionó? He estado usando el XJC distribuido con JDK 7, así que tal vez las versiones anteriores funcionen con esto. Sé que quieres "forzar" el elemento hola configurando un String vacío para él, y ese ** es ** el enfoque correcto. Establecer nulo daría como resultado que se omita. Pero nuestro objetivo aquí es convertir el campo de saludo en la clase 'Epp' en un tipo concreto, ya que es un' Objeto' que es lo que está causando que se agregue toda la pelusa xsi: tipo. –

+0

Ah, bueno, he decidido para hacer el modo "atornillar" ya que inicialmente hice cambios en las partes xsd para hacer que JAXB sea compatible (@XmlRootElement missing stuff;)). E hizo lo que le dijiste: he cambiado el xsd para decir que el elemento hola es de tipo cadena. '' y seguir usando el mismo código Java me da el resultado que prefiero. Ahora espero que mi XSD aún sea compatible con la recepción de estos hola, pero tendré que probar que ... –

1

Cuando el esquema no especifica un tipo para un elemento, el tipo predeterminado es xs:anyType, que es la raíz de la jerarquía del tipo de esquema XML (todos los tipos simples y complejos son subtipos de anyType).

Cuando JAXB encuentra un elemento anyType, lo vinculará a una propiedad del tipo Object. El valor que puso en esta propiedad puede ser

  • null, significado omitir el elemento
  • un objeto de un tipo del JAXBContext conoce, que será marshalled de la forma habitual y un xsi:type añadido para indicar lo que el el tipo original era, o
  • un org.w3c.dom.Element que representa el XML real a usar.

Así que trate esto:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
dbf.setNamespaceAware(true); 
Document doc = dbf.newDocumentBuilder().newDocument(); 

epp.setHello(doc.createElementNS("urn:ietf:params:xml:ns:epp-1.0", "hello")); 
Cuestiones relacionadas