How to avoid unnecessary namespace declarations in a marshalling element / tag?

I have an XSD that is not created on its own, but received from the other side. Therefore, I cannot change this XSD, because I have to ensure compatibility with the other side.

Using XJC 2.2 and JAXB 2.2, using simple binding mode, I want to create a root element inside an empty hello element. But when I gathered a lot of extra space for storing names. Which seems unnecessary to me. (It works though, but more data to send ect ...)

XSD Rootelement:

<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 Code:

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

Marshalling result:

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

Preferred Result:

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

Or:

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

Is there a way to make this possible, preferably without modifying the XSD or manually modifying the compiled XJC classes?

+6
source share
2 answers

The problem is this: the schema does not determine the type of the hello element. As a result, XJC creates a field of type Object . This means that JAXB must determine what object we are dealing with during sorting. I'm not sure about the details, but I assume that he will check the type of runtime and then process it accordingly. Since String - this is what you actually put in the hello field - has a direct binding to the type of schema (namely xs:string ), JAXB is going to go with that. So far so good.

But JAXB is trying to generate XML, which will be useful for unmarshalling. Since the schema did not specify a type, and the hello field is an object, trying to decouple it with XML would leave JAXB guessing what it would turn the content into. One way to tell how to specify a type in an XML element is using the xsi:type attribute. This attribute falls into the xsi -bound namespace, so the prefix must be declared and bound. What happens with xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" . But that’s not all ... Declared xsi:type uses a type in the XML Schema namespace bound to the xs prefix, which means that this must also be declared! Therefore, xmlns:xs="http://www.w3.org/2001/XMLSchema" .

Result: the mess of namespace declarations simply to tell who uses the XML, what he does, actually contains a string. This can be solved by adding a string as a type for the hello element in the schema, but this is not an option for you.

Fortunately, you are not completely out of luck. You can configure the bindings using an external binding file. Details can be found here: http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html

Usually this binding file should do the trick:

 <?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> 

... but when I try xjc with this, I get the compiler was unable to honor this javaType customization . It works when I specify some standard schema type (like string or int) in the hello element in the schema, but it didn’t work again when I actually tried to provide parsing and printing methods for the conversion, so I’ll assume that this is an error in xjc that occurs when a type is not specified in the schema.

I hope someone else can give advice regarding binding problems. Otherwise, the only option I can see is sending your schema through some XSLT transform before deploying XJC on it, so that by default every untyped element is set.

+4
source

If the schema does not indicate the element type, the default is xs:anyType , which is the root of the type hierarchy of the XML schema (all simple and complex types are subtypes of anyType ).

When JAXB encounters anyType , it will bind it to a property of type Object . The value specified in this property may be

  • null , which means omit the item
  • an object of the type that JAXBContext knows about, which will be ordered in the usual way and added xsi:type to indicate that the source type was, or
  • an org.w3c.dom.Element representing the actual XML used.

So try the following:

 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")); 
+1
source

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


All Articles