JAXB namespace prefixes missing - java

I have generated Java classes from XSD, all works fine from a unmarshalling point of view.
However, when I marshall from JAXB classes I get the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<message xmlns="http://poc.cmc.com/ScreenLayout">
<Data>
<Type>Sample</Type>
. . .
</message>
But I need
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns0:message xmlns:ns0="http://poc.cmc.com/ScreenLayout">
<ns0:Data>
<ns0:Type>Sample</ns0:Type>
. . .
how can I control that from Java?
Thanks a lot

You can use the #XmlSchema annotation on a package-info class to assign a prefix to the namespace:
#XmlSchema(
namespace = "http://poc.cmc.com/ScreenLayout",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns={#XmlNs(prefix="ns0", namespaceURI="http://poc.cmc.com/ScreenLayout")})
package your.package;
import javax.xml.bind.annotation.*;

Cant post this as a comment!
because the consuming application is very dumb and needs the prefix
In that case the dumb application is not really consuming xml. Take a look at this link http://bdoughan.blogspot.com/2010/08/jaxb-namespaces.html and play with the namespace options. Specifically
#XmlSchema (
xmlns = {
#javax.xml.bind.annotation.XmlNs(prefix = "ns1", namespaceURI="http:test"),
#javax.xml.bind.annotation.XmlNs(prefix = "xsd", namespaceURI="http:www.w3.org2001XMLSchema")
},
namespace = "http:test",
elementFormDefault = XmlNsForm.UNQUALIFIED,
attributeFormDefault = XmlNsForm.UNSET
)
used in a package-info.java file.
#XmlType(namespace="http://www.example.org/type")
Used on a class declaration
#XmlElement(namespace="http://www.example.org/property")
Used on a property.
Some combination or only one of these options may give you what you want. However you should understand that you're fighting an uphill battle when you move from valid xml to xml that must contain a specific namespace prefix on all elements.

According to XML spec both xml's are the same, as xmlns="" defines default namespace which applies to current and all child elements.
XML parsers should give you the same DOM or SAX in both cases

I did the following steps and everything works. Basically I've compiled form the wsdl or whatever schema file you have.
Download from
https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-ri/ (I've used version 2.3.4)
With the following command:
xjc.sh -wsdl -npa -mark-generated -d src/main/java -p your.package.hierarchy src/main/resources/wsdl/*
I had wsdl files and that's the reason for the first flag, the -npa is to add the namespace information in the annotation rather than on a package-info.java since for some reason that wasn't working for me.

Related

How to force XJB to generate the classes, marshalling the XML code with the namespace without prefix independently on exact namespace value?

I have the situation there is an web service implemented in old Visual Studio 2008, which accepts the SOAP requests with content having namespaces only in this form:
<Root xmlns="http://A">
<A>
<A1 />
</A>
<B xmlns="http://B">
<B1 />
</B>
</Root>
All other forms of the XML (unqualified, or qualified with namespace prefix) are causing problems even if the wsdl and referenced xsd structures are manipulated and modified in various ways and the service is recompiled in Visual Studio 2008, the author of the ASP.NET web service is not able to get any other form of XML working.
Is there any way how to achieve the generation of the classes for our Java client accessing this web service by using the external JAXB binding specification, used during the class generation, so the XML would be from the objects marshalled in the above described form?
Am I right, if I think, this could be achieved by the forcing the JAXB to generate the class(ses in multiple directories)
package-info.java
instead of the default form
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://some/custom/namespace",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package some.custom.namespace;
in the following form?
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://some/custom/namespace",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {#XmlNs(prefix = "", namespaceURI = "http://some/custom/namespace")})
package some.custom.namespace;
and if I am right, is there any way to do it? I am unfamiliar with writing the XJB bindings, so any pointer would be appreciated...
Or maybe, after the generation the source code of this class should be postprocessed by something like ant task, which would modify the initially generated JAXB form into the form I think it was the desired content of the class package-info.java?
Could this be somehow achieved by one universal jxb binding file for all usages without necessity to modify it for every namespace folder creating its own package?
I hope this could really work even with multiple different namespaces without prefixes, because the xmlns definitions are then used in JAXBContextImpl as a set of XmlNs types, so if there is an prefix or not hopefully should not matter... Am I right?

How to move xmlns:xs and xmlns:xsi to Root Element with JAXB?

I need to generate XML files from XSD generated Java Classes.
Some of the fields in those Java Classes as Object instead of any concrete type, and thus warrant a xsi:type attribute in the generated XML file, which is fine.
What is NOT fine though is that along with that xsi:type, the full namespace definition is added (xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"), and makes the XML very unreadable.
To sum it up, here is what I generate now:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns:RootTag xmlns:ns="https://example.com">
<ns:SomeObjectField xsi:type="xs:boolean" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">true</ns:SomeObjectField>
<ns:SomeOtherObjectField xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Some other value</ns:SomePtherObjectField>
</ns:RootTag>
And this is what I would like to generate:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns:RootTag xmlns:ns="https://example.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns:SomeObjectField xsi:type="xs:boolean">true</ns:SomeObjectField>
<ns:SomeOtherObjectField xsi:type="xs:string">Some other value</ns:SomePtherObjectField>
</ns:RootTag>
I had the same issue. The solution assuming you are using the marshaller of the JAXBContext, you can set a property for your namespace or schema location property. In my case I needed a noSchemaLocation:
jaxbMarshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "facturaComputarizadaEstandar.xsd");
You might need to set a different property for your specific case.
You can explicitly declare xsi in package-info.java:
#javax.xml.bind.annotation.XmlSchema(
xmlns = {
#javax.xml.bind.annotation.XmlNs(
prefix = "ns",
namespaceURI = "https://example.com"),
#javax.xml.bind.annotation.XmlNs(
prefix = "xsi",
namespaceURI = javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI) },
namespace = "https://example.com",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.foo;
prefix = "ns": <ns:RootTag>
prefix = "": <RootTag>
See JAXBContextImpl.xmlNsSet
NamespaceContextImpl.declareNsUri()
JAXBContextImpl.schemaLocation
In the older jaxb implementation 2.1 the #XmlNs is only used when generating a schema file and as a workaround you can add:
#XmlSeeAlso(DummyTypeWithinXsi.class)
public class RootTag ...
...
#XmlRootElement(namespace = javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)
public class DummyTypeWithinXsi {
}
_

JAXB multiple namespaces with same prefix

This is my first question on StackOverflow in general, so please bear with me.
I have an issue with marshalling XML that uses the default prefix for different namespaces. Each element that uses the default prefix should specify its namespace in its opening tag. An example what I'm trying to achieve would be something like this (simplified):
<parent xmlns="parentNamespace" xmlns:cd1="child1Namespace">
<cd1:child1/>
<child2 xmlns="child2Namespace">
...
</child2>
<child3 xmlns="child3Namespace">
...
</child3>
</parent>
I have tried setting namespaces prefixes in package-info.java of the object I'm trying to marshall using annotations like this:
#javax.xml.bind.annotation.XmlSchema(
namespace = "parentNamespace",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(prefix="",parentNamespace"),
#XmlNs(prefix="cd1", namespaceURI="child1Namespace"),
#XmlNs(prefix="", namespaceURI="child2Namespace"),
#XmlNs(prefix="", namespaceURI="child3Namespace")
}
)
But the end result is something like this:
<ns1:parent xmlns:ns1="parentNamespace" xmlns:cd1="child1Namespace" xmlns="child2Namespace xmlns:ns2="child3Namespace"<
<cd1:child1/>
<child2>
...
</child2>
<ns2:child3>
...
</ns2:child3>
</ns1:parent>
Which really is a valid XML, but unfortunately for reasons that are outside my control isn't good enough (doesn't pass validation). Also note that solution using Java 8 is highly preferable as I wouldn't want to mess with NamespacePrefixMapper if at all possible (if it even works).
So the question is: Is it possible to generate XML using JAXB that uses same prefix for multiple namespaces and how?

Missing namespace in the javas generated by wsimport

When using wsimport the "standard" way:
wsimport.exe -d C:/temp/generatedClasses -s C:/temp/sourceFiles C:/temp/myWsdl.wsdl
I get source files generated like this:
#XmlRootElement(name = "PingRequest")
public class PingRequest{
Last time the classes were generated the same WSDL/ XSDs should have been used and generated a output like this:
#XmlRootElement(name = "PingRequest", namespace = "http://me.foo.bar/any/")
public class PingRequest {
So the schemas namespace was included as attribute of the annotation. Since the generated class package-info.java has the following entry:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://me.foo.bar/any", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
I assume adding the namespace-attribute is a done by configuration of wsimport/ jaxb schema compiler.
Could anyone explain me how to archive the namespace attribute beeing included?
Update: As Blaise answered correctly (described in the blog-link) the generated file package-info.java defines the namespace for all classes/ types inside the according package. Above example is obsolete if always the same namespace is included per #RootElement. Setting namespaces on #RootElement level may be used to have a certain #RootElement have its own namespace (which in case of wsimport should happen automaticially).
Very many thanks for any suggestions
What i tried:
used google, found https://www.java.net/node/681149 (exaclty my question from back in 2008) with no answer :(
read wsimport/ jaxb schema compiler options, tried out various that only controlled package ouput
read 12 similar question/ answer that poped up when i typed in the title of this question
Closest i found that has something to do with the namespaces was to have 'elementFormDefault="qualified' specified in both the XSD itself and the import part inside the WSDL which i have done.
Specifying the following annotation at the package level, and not specifying the namespace on all the #XmlElement/#XmlRootElement annotations.
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://me.foo.bar/any",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
Is the equivalent to not having #XmlSchema and adding the namespace parameter to all the #XmlElement/#XmlRootElement annotations. They will produce/consume the same XML documents.
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html

Add Xml namespace using Jaxb

I am creating amazon feed, the feed xml should be like:
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
I am using jaxb to generate xml files from java classes, I used NamespacePrefixMapperImpl from jaxb samples to add namespaces to the xml. But currently it generates the root like:
<AmazonEnvelope xmlns:xsi:noNamespaceSchemaLocation="amzn-envelope.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
how I can remove the xmlns from amzn-envelope.xsd??
Here's the mapping I used in NamespacePrefixMapperImpl
if( "http://www.w3.org/2001/XMLSchema-instance".equals(namespaceUri) )
return "xsi";
if("amzn-envelope.xsd".equals(namespaceUri))
return "xsi:noNamespaceSchemaLocation";
I found a property at Marshaller that can add the amzn-envelope.xsd:
marshaller.setProperty("jaxb.noNamespaceSchemaLocation", "amzn-envelope.xsd");
and left the NamespacePrefixMapper to add the "http://www.w3.org/2001/XMLSchema-instance".
Hope this helps others.
If I understand your intent, your document has a default namespace, and you're trying to add the schemalLocation for that namespace.
NamespacePrefixMapper won't let you do this, it's useful only for picking a prefix for a namespace. There are no namespaces in this document, and so no useful way of using NamespacePrefixMapper. It can't be used for adding schemaLocation hints - those are treated specially by JAXB, and you're just confusing it.
Are you sure you need the noNamespaceSchemaLocation="amzn-envelope.xsd" at all? Have you tried sending it to the web service without it?

Categories

Resources