2012-06-08 17 views
6

Actualmente estoy Marshalling un objeto JAXB a un flujo de salida con el siguiente código¿Cómo conseguir el espacio de nombres de un objeto JAXB

marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); 
ByteArrayOutputStream out = new ByteArrayOutputStream(); 
marshaller.marshal(new JAXBElement(new QName("hard_coded_namespace", clazz.getSimpleName()), clazz, obj), out); 

quisiera sustituir "hard_coded_namespace" con el espacio de nombres que aparecen en la JAXB " obj "(o uno de sus atributos, actualmente deberían compartir el mismo NS).

¿Alguna idea de cómo obtener la información de NS ANTES de ordenar? En la secuencia de salida, aparecen los espacios de nombres. Entonces están en algún lugar del "obj".

[ACTUALIZACIÓN] Como se señala en las respuestas a continuación, no es necesario configurar la propiedad JAXB_FRAGMENT. Lo cambié a:

JAXB.marshal(new JAXBElement<T>(new QName("hard_coded_namespace", rootName), clazz, jaxbObject), out); 

Respuesta

4

Por ahora, esta es la solución que encontré:

String nsURI = ""; 
    for(Annotation annotation: jaxbObject.getClass().getPackage().getAnnotations()){ 
     if(annotation.annotationType() == XmlSchema.class){ 
      nsURI = ((XmlSchema)annotation).namespace(); 
      break; 
     } 
    } 

soluciones más elegantes son bienvenidos :-)

+1

la información del espacio de nombre estaba en 'package-info.java' – Chris

+1

, dependiendo de qué tan general sea su solución, no hay garantía de que la información del paquete. la clase será generada por xjc (ver la opción -npa). – kschneid

1

¿Necesita usar esa API Marshal? Hay una sobrecarga más simple. Mientras la clase en tiempo de ejecución de obj tiene la @XmlRootElement anotación, usted debe ser capaz de llamar simplemente

marshaller.marshal(obj, out); 
+0

En este caso, no tengo el atributo XmlRootElement establecido en la clase del objeto. La API de Marshaller es necesaria para que pueda indicar que se trata de un JAXB_FRAGMENT, es decir, un elemento sin un XmlRootElement. Por favor corrígeme si estoy equivocado. – Chris

+0

En realidad, estoy haciendo exactamente lo que usted recomienda. Es difícil de leer debido a la nueva JAXBElement() en el medio ... :-). – Chris

1

El uso de la propiedad Marshaller.JAXB_FRAGMENT realmente no tiene nada que ver con elementos que no son raíz de procesamiento. Actúa como una bandera para determinar si ciertos eventos de clasificación deben ser acelerados. Por ejemplo, si la propiedad está configurada, no se generarán eventos de documento de inicio y fin.

No he probado los siguientes, pero aquí es una idea básica de cómo me gustaría crear un código de utilidad para encontrar el QName de un objeto JAXB dado:

  • If JAXBIntrospector.isElement vuelve verdad, entonces sólo tiene que utilizar JAXBIntrospector.getElementName.
  • utilizar la reflexión para encontrar un método en la clase ObjectFactory en el mismo paquete que el objeto JAXB que devuelve JAXBElement y toma un solo argumento de que es una instancia de la misma clase que el objeto JAXB . Invoca ese método y luego usa JAXBElement.getName.
+0

gracias por su respuesta! isElement() devuelve falso en los objetos con los que estoy tratando. – Chris

+1

está bien, la segunda viñeta debe cubrir esa condición ... – kschneid

0
JAXBContext jaxbCtx = JAXBContext.newInstance(Instance.class); 
QName qname = jaxbCtx.createJAXBIntrospector().getElementName(instance); 
0

Si no hay @XmlRootElement de la clase a serialize, no hay otra forma de buscar la declaración del paquete en sí (JAXBIntrospector no funcionará):

private <T> QName getQName(final Class<T> clazz) { 
    // No other way since it is not @RootXmlElement 
    final String xmlns; 
    final Package aPackage = clazz.getPackage(); 
    if (aPackage.isAnnotationPresent(XmlSchema.class)) { 
     xmlns = aPackage.getDeclaredAnnotation(XmlSchema.class).namespace(); 
    } else { 
     xmlns = ""; // May throw illegal 
    } 
    return new QName(xmlns, clazz.getSimpleName()); 
} 
Cuestiones relacionadas