JAXB Unmarshalling Error, package-info file for no namespace? - java

I am attempting to Unmarshall XML from a file using JAXB. I also have a web service.
I want to use no namespace, not the namespace defined by the web service.
I am getting the following error:
Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"CustomerName"). Expected elements are <{http://www.ws.NET}CustomerName>
I think that the solution is to change the package-info.java file to use no namespace. Is this the correct approach? and what changes should I make to this file?
The package-info.java file looks as follows:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.ws.NET", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package mynewpackage;
Thanks for your help

Changing QUALIFIED to UNQUALIFIED will help if the top-level element (corresponding to the #XmlRootElement annotated class) is in the target namespace but its children aren't, e.g.
<ns:Response xmlns:ns="http://www.ws.NET">
<CustomerName>Ian</CustomerName>
</ns:Response>
but this won't help if the top level (in this case Response) element is also unqualified.

When you have a JAXB model that is annotated to be namespace qualified and you want to unmarshal XML that isn't there are a couple of options.
If You Can Change the Model
You may just need to remove the #XmlSchema annotation from the package-info class. If there are no other package level annotations you could remove the whole class. Note that namespace information may also be specified on other annotations such as #XmlElement.
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
If You Can't Change The Model
If you can't change the JAXB model to remove the namespace qualification then you can leverage a SAX XMLFilter to apply a namespace to the XML as it's being read.
http://www.stackoverflow.com/questions/14609597/how-flexible-is-jaxb/14610836#14610836

Related

JAXB unmarshall xml without package-info.java

JAXB unmarshaller throws exception if there is no package-info.java file. This code is called from another language and custom classloader can not load package-info properly.
I had already manually added the namespace parameter to all the #XmlElement annotations.
Xml root element has multiple xmlns attributes. Two of them (xmlns and xmlns:c) have the same value (I can not change xml, which is comeing from external service)
BUT: It works if I remove xmlns="urn:foo:bar" from document even without package-info
The question: how can I unmarshall without package-info (I can not modify custom classloader which can not load it) and without removing xmlns from xml ?
What should I change in my code?
Java 1.6_45 vJAXB 2.1.10
XML root element sample:
<?xml-stylesheet type="text/xsl" href="file1.xslt">
<?xml-stylesheet type="text/xsl" href="file1.xslt"?>
<c:ClinicalDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:foo:ba" xmlns:c="urn:foo:bar" xmlns:std="urn:foo:std"
xsi:schemaLocation="urn:foo:bar file2.xsd">
Code:
String path = "D:\\data\\document.xml";
try {
JAXBContext jc = JAXBContext.newInstance(ObjectFactory.class);
Unmarshaller u = jc.createUnmarshaller();
Object root = u.unmarshal(new File(path)); //exception w/o package-info.java
CDocument doc= (CDocument) JAXBIntrospector.getValue(root);
System.out.println(doc);
package-info.java
#javax.xml.bind.annotation.XmlSchema(namespace = "urn:foo:bar", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns={#XmlNs(namespaceURI = "urn:foo:bar", prefix = "")})
package test.model;
import javax.xml.bind.annotation.XmlNs;
Exception:
javax.xml.bind.UnmarshalException: Unable to create an instance of my.package.here.model.ANY
Any ideas will be greatly appreciated, I had spent so much time trying, but still have nothing.
BUT: It works if I remove xmlns="urn:foo:bar" from document even without package-info
This means that you have not added the namespace parameter everywhere you need to.
In the XML document below without the #XmlSchema annotation to map the namespace qualification, you would require the namespace parameter on the #XmlRootElement annotation for the Foo class and the #XmlElement annotation on the bar property.
<foo xmlns="http://www.example.com">
<bar>Hello World</bar>
</foo>

JAXB classes for same parent and child tag name

I have run into weird problem. I have one xml response coming from the server and the demo xml looks like:
http://www.javaexperience.com/catalog.xml
The root and one of the child tag have same name "Catalog" but different xml hierarchy.
When I run JAXB processor on the xsd generated from this xml, I get the error because Catalog.java was already generated from root tag and now can't be generated for child tag.
How should I resolve this problem.
P.S. I used http://xmlgrid.net/xml2xsd.html for getting xsd from demo xml.

JAXB Namespace translation in a AXIS2 WebService application on Tomcat 7

I've used xjc of jaxb 2.2.6 to generate a set of classes from a xsd file.
By editing "package-info.java" I've associated to the different namespaces the prefix value.
So I've created a Test Class with a main that Unmarshal an xml file, edit some information, and marshal the object in xml format.
Everything works like a charm and javax.xml.bind.Marshaller object match correctly namespace and prefix as defined in package-info.
When I deploy this application as WS using axis2 on tomcat7 in the same machine and call a ws method that execute the code described above javax.xml.bind.Marshaller create an xml file with default namespace (ns1, ns2....).
The package-info.java that I've used is something like this:
#javax.xml.bind.annotation.XmlSchema(
namespace = "....",
xmlns = {
#XmlNs(namespaceURI = "....", prefix = "myprefix"),
#XmlNs(namespaceURI = "...", prefix = "myprefix2"),
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package ....;
import javax.xml.bind.annotation.XmlNs;
This is a piece of right output (This output is obtained when I execute the code as "Java Application"):
.....
<ContactInformation>
<rm:ContactDescription>ASD</rm:ContactDescription>
<rm:ContactRole>ASD</rm:ContactRole>
<rm:ContactLocation/>
<rm:AdditionalContactInformation>
<xnl:PartyName>
<xnl:PersonName>
<xnl:NameElement xnl:ElementType="FirstName">ASD</xnl:NameElement>
<xnl:NameElement xnl:ElementType="LastName">ASD</xnl:NameElement>
</xnl:PersonName>
<xnl:OrganisationName>
<xnl:NameElement>ASD</xnl:NameElement>
</xnl:OrganisationName>
</xnl:PartyName>
</rm:AdditionalContactInformation>
</ContactInformation>
......
This is a piece of wrong output (This output is obtained when I execute the code inside an "Axis2/Tomcat7 WS Application"):
.....
<ContactInformation>
<ns2:ContactDescription>ASD</ns2:ContactDescription>
<ns2:ContactRole>ASD</ns2:ContactRole>
<ns2:ContactLocation/>
<ns2:AdditionalContactInformation>
<ns7:PartyName>
<ns7:PersonName>
<ns7:NameElement ns7:ElementType="FirstName">ASD</ns7:NameElement>
<ns7:NameElement ns7:ElementType="LastName">ASD</ns7:NameElement>
</ns7:PersonName>
<ns7:OrganisationName>
<ns7:NameElement>ASD</ns7:NameElement>
</ns7:OrganisationName>
</ns7:PartyName>
</ns2:AdditionalContactInformation>
</ContactInformation>
......
For each case exists a package-info.java where namespaces translation are declared.
How can I resolve this issue?
A JAXB (JSR-222) implementation is not required to use the prefixes as defined in the #XmlSchema annotation. The prefixes are used are not significant, and the namespace qualification between JAXB (JAX-WS) implementations will be the same although the prefixes may be different.

Custom name space JAXB, XML

I want to map following xml using custom name sapace. I checked How to have custom namespace prefix but could not find any answer.
<p385:execute xmlns:p385="http://tal.myserver.com">
<version xsi:type="xsd:string">0.1.0</version>
<xmlData xsi:type="xsd:string">
.... xml encoded data
</xmlData>
</p385:execute>
How can i map this to a java class?
Since it is only the root element that is namespace qualified, you just need to specify the namespace on the #XmlRootElement annotation for the class.
#XmlRootElement(namespace="http://tal.myserver.com")
public class Execute {
}
You can the suggest the prefix that should be used for the namespace using the package level #XmlSchema annotation:
http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html
Use the wsimport tool to generate artifacts such as JAXB classes from a WSDL:
http://docs.oracle.com/javase/7/docs/technotes/tools/share/wsimport.html
http://jax-ws-commons.java.net/jaxws-maven-plugin/wsimport-mojo.html

Setting Namespace Attributes on an Element

I'm trying to create an XML document in Java that contains the following Element:
<project xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2"
xmlns:acme="http://www.acme.com/schemas"
color="blue">
I know how to create the project Node. I also know how to set the color attribute using
element.setAttribute("color",
"blue")
Do I set the xmlns and xmlns:acme attributes the same way using setAttribute() or do I do it in some special way since they are namespace attributes?
I believe that you have to use:
element.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:acme", "http://www.acme.com/schemas");
I do not think below code will serve the question!
myDocument.createElementNS("http://www.imsglobal.org/xsd/ims_qtiasiv1p2","project");
This will create an element as below (using DOM)
<http://www.imsglobal.org/xsd/ims_qtiasiv1p2:project>
So this will not add an namespace attribute to an element. So using DOM we can do something like
Element request = doc.createElement("project");
Attr attr = doc.createAttribute("xmlns");
attr.setValue("http://www.imsglobal.org/xsd/ims_qtiasiv1p2");
request.setAttributeNode(attr);
So it will set the first attribute like below, you can set multiple attributes in the same way
<project xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2>
The short answer is: you do not create xmlns attributes yourself. The Java XML class library automatically creates those. By default, it will auto-create namespace mappings and will choose prefixes based on some internal algorithm.
If you don't like the default prefixes assigned by the Java XML serializer, you can control them by creating your own namespace resolver, as explained in this article:
https://www.intertech.com/Blog/jaxb-tutorial-customized-namespace-prefixes-example-using-namespaceprefixmapper/
You can simply specify the namespace when you create the elements. For example:
myDocument.createElementNS("http://www.imsglobal.org/xsd/ims_qtiasiv1p2","project");
Then the java DOM libraries will handle your namespace declarations for you.
The only way that worked for me, in 2019, was using the attr() method:
Element element = doc.createElement("project");
element.attr("xmlns","http://www.imsglobal.org/xsd/ims_qtiasiv1p2");

Categories