How to get JAXB object namespace

I am currently assembling a JAXB object in the output stream with the following code

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); 

I would like to replace "hard_coded_namespace" with the namespace contained in JAXB "obj" (or one of its attributes, they must currently have the same NS).

Any ideas on how to get NS information before marshaling? Namespaces appear in the output stream. Therefore, they are located somewhere in "obj".

[UPDATE] As indicated in the answers below, I do not need to set the JAXB_FRAGMENT property. I changed it to:

  JAXB.marshal(new JAXBElement<T>(new QName("hard_coded_namespace", rootName), clazz, jaxbObject), out); 
+6
source share
5 answers

At the moment, this is the solution I found:

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

More elegant solutions are welcome :-)

+4
source

Do you need to use the marshal's API? The simplest overload. As long as the obj runtime class has the @XmlRootElement annotation, you should just call

 marshaller.marshal(obj, out); 
+1
source

Using the Marshaller.JAXB_FRAGMENT property really has nothing to do with handling elements other than root. It acts as a flag to determine whether certain marshaling events should be restricted. For example, if the property is set, then document start and end events will not be generated.

I have not tested the following, but here is the basic idea of โ€‹โ€‹how to create the utility code to find the QName this JAXB object:

  • If JAXBIntrospector.isElement returns true, just use JAXBIntrospector.getElementName .
  • Use reflection to find the method in the ObjectFactory class in the same package as the JAXB object, which returns a JAXBElement and takes one argument, which is an instance of the same class as the JAXB object. Call this method and then use JAXBElement.getName .
+1
source
 JAXBContext jaxbCtx = JAXBContext.newInstance(Instance.class); QName qname = jaxbCtx.createJAXBIntrospector().getElementName(instance); 
0
source

If there is no @XmlRootElement in the class for serialization, there is no other way to find the package declaration itself (JAXBIntrospector will not work):

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

Source: https://habr.com/ru/post/917638/


All Articles