remove xmlns attribute from the root element while marshalling jaxb - java

This might be a related to JAXB Marshaller - How do I suppress xmlns namespace attributes?
But my problem is a little different.
I do the regular java marshalling and my xsd has no namespaces.The generated xml is without namespaces as well, except for the root element.
<?xml version="1.0" encoding="UTF-8"?><rootElement xmlns:ns2="unwanted namespace">
The unwanted namespace is from another schema from the same project and I am not sure why that is being picked up at this stage.
My rootElement.java generated by jaxb2-maven-plugin looks like :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"feed"
})
#XmlRootElement(name = "rootElement", namespace = "")
public class RootElement{
....
}
At this point all I want is to get rid of the xmlns:ns2="unwanted namespace" attribute from the generated xml and I am struggling with it.
I looked at my package-info.java and it looks like:
#javax.xml.bind.annotation.XmlSchema(namespace = "unwanted namespace", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.mypackage;
I tried adding he -npa but it wont work on jaxb2-maven-plugin for some reason. I tried the NamespaceMapper but that works for changing prefixes. I could not get it to remove the namespace altogether. This is bothering me for a day now.

I have similar requirements at the moment. The only solution that worked for me is implementing a wrapper for XMLStreamWriter.
Please, take a look at my answer here. I've also described there other solutions I tried out.
Serialization using code from the link above looks like this:
XMLOutputFactory factory = XMLOutputFactory.newFactory();
StringWriter writer = new StringWriter(XML_BUFFER_INITIAL_SIZE);
XMLStreamWriter xmlWriter = null;
try {
xmlWriter = factory.createXMLStreamWriter(writer);
JAXBContext context = JAXBContext.newInstance(MyJAXBGeneratedClass.class);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(reportContainer, new NamespaceStrippingXMLStreamWriter(xmlWriter));
xmlWriter.flush();
}
finally {
if (xmlWriter != null)
xmlWriter.close();
}
return writer.toString();

Related

JAVA XML Parsing with namespaces using JAXB annotations

I have a huge XML response from an external end point. I want to parse the XML response to java classes. I was able to parse into respective POJOS if none of the XML had namespaces and things went well till that point.
However, the response might contain namespaces only at the root element.
For eg, like this
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="somevalue here"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RestOfTheDocument> something here </RestOfTheDocument>
</Document>
I can guarantee that none of the inner xml elements will have any more namespaces.
Is there a way to implement this? I saw a few answers ignoring namespaces completely but dont feel very convincing. Is there a way to properly parse these.
This is my java class to model the XML response
#XmlRootElement(name = "Document")
static class Response {
#XmlElement(name = "RestOfTheDocument", required = true, nillable = false)
RestOfTheDocument restOfTheDocument;
}
what I tried ?
Add namespace information to the #XmlRootElement like this
#XmlRootElement(name = "Document", namespace = "somevalue here")
Doing so is making all the inner xml elements to be NULL.
NOTE: I have abstracted the huge inner level to be RestOfTheDocument but there are lot many but none of them will have any namespaces whatsoever in the response!
Thank you!
SimpleXml will ignore the namespaces and just parse the XML:
public class Document {
public String RestOfTheDocument;
}
final String data = ...;
final SimpleXml simple = new SimpleXml();
final Document document = simple.fromXml(data, Document.class);
System.out.println(document.RestOfTheDocument);
This will output:
something here
From maven central:
<dependency>
<groupId>com.github.codemonstur</groupId>
<artifactId>simplexml</artifactId>
<version>1.4.0</version>
</dependency>

How do I tell the JAXB marshaller to use the schemaLocation provided in my beans' package-info?

I'm trying to get my JAXB marshaller to use the provided schemaLocation without using
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "some location");
I see that there is an option to provide a schema location in my
package descriptor
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://my.website.com/TheClass"
, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED
, location = "http://my.website.com/TheClass TheClass.xsd"
)
package com.mypackage.beans;
but it won't print in the xml
I assume that your main issue is that the generated XML from your marshaller misses the required name space.
Have you tried adding the xmlns={#XmlNs(prefix="your_name_space", namespaceURI="http://my.website.com/TheClass")}
in your XmlSchema annotation in your package descriptor?
(Suggestion taken from: JAXB namespace prefixes missing)

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>

javax.xml.bind.UnmarshalException: Unexpected element. What am i missing?

I am doing this,
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[] {
mine.beans.ObjectFactory.class });
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
orderhistory = (OrderHistory) unmarshaller.unmarshal(new StreamSource(
new StringReader(responseXML)));`
I am getting javax.xml.bind.UnmarshalException: Unexpected element "OrderHistory". Expected elements are "{_http://orderhistory.shc.com/common/domain}OrderHistory". but i checked my OrderHistory.java i have the
#XmlRootElement(name = "OrderHistory")
public class OrderHistory{
What am i missing???
Even the package-info.java file is also present
Here is my response xml,
<?xml version="1.0" encoding="UTF-8"?>
<OrderHistory>
<guid>5555</guid>
<syNumber xsi:nil="true"></syNumber>
<email xsi:nil="true"></email>
<totalPages>0</totalPages>
</OrderHistory>
Still i am facing the same issue???
I ve made changes to my package-info.java i have removed the namespace attribute but still i am seeing the same issue,
#javax.xml.bind.annotation.XmlSchema()
package mine.beans;
It appears as though your input document is not namespace qualified.
You have:
<OrderHistory>...</OrderHistory>
And your JAXB (JSR-222) implementation is expecting:
<OrderHistory xmlns="_http://orderhistory.shc.com/common/domain">...</OrderHistory>
Related
If you are unmarshalling from a DOM, make sure to call setNamespaceAware(true) on the instance of DocumentBuilderFactory.
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
As hint. Try to marshal the document from your object, and see if the tags are written as expected.
Did you try to modify your XML? Your UNmarshaller is expecting the OrderHistory-Element to be part of the "http://orderhistory.shc.com/common/domain" namespace, and yet it isnt. You could give this a try:
<?xml version="1.0" encoding="UTF-8"?>
<OrderHistory xmlns="_http://orderhistory.shc.com/common/domain">
<guid>5555</guid>
<syNumber xsi:nil="true"></syNumber>
<email xsi:nil="true"></email>
<totalPages>0</totalPages>
</OrderHistory>

JAXB to unmarshall <string>foobar</string>

Greetings! I have a server returning XML content to my client that looks like this:
<string xmlns="...">foobar</string>
I'm new to JAXB and have gotten a lot of stuff working, except this. I thought it would be pretty easy to marshal and unmarshal this to and from a String. It took a while, but I finally figured out how to marshal this as
public static String ToXML(String s) throws Exception
{
JAXBContext context = JAXBContext.newInstance(String.class);
Marshaller marshaller = context.createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(new JAXBElement(new QName("", "String"), String.class, s), sw);
return sw.toString();
}
So my question is, how to I unmarshal this? It cannot be annotated as a root element. I cannot use java.lang as the package to create a new instance of a JAXBContext (I get an ObjectFactory missing exception).
Any wisdom to impart? This can't be that hard, right?
You need to write an object model that conforms to your XML structure, and tell JAXB to unmarshal on to that. Your example may look simple, but it's not what JAXB is for.
Try something like this:
#XmlRootElement(name="string", namespace="blah")
public class MyString {
#XmlValue
String value;
}
JAXBContext context = JAXBContext.newInstance(MyString.class);
MyString myString = (MyString) context.createUnmarshaller().unmarshal(...);
This will unmarshal the XML <string xmlns="blah">foobar</string>. Change the namespace accordingly. If you have many namespaces, then JAXB isn't really the tool for you.
I was surprised by this, but the following seems to work:
final String xmlString = "<string>value</string>";
final StringReader xmlReader = new StringReader(xmlString);
final StreamSource xmlSource = new StreamSource(xmlReader);
final JAXBContext jaxbContext = JAXBContext.newInstance(String.class);
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
final String stringValue = unmarshaller.unmarshal(xmlSource, String.class).getValue();
Is that what you were looking for?
When you're using JAXB, you need to build the code around an XML schema. That is, if you have a file, say foo.xsd, you need to run it through the xjc compiler (in JDK 6 by default, otherwise you can download JAXB 2 and use that). That will read through the schema and generate the Java bean and associated ObjectFactory classes with the elements in the schema. The Java bean classes will look like regular POJOs with annotations. The ObjectFactory classes are needed by the JAXB implementation to convert the XML into the corresponding Java bean. This explains your ObjectFactory missing exception.
So it's not hard, but there is some leg work involved. We use it for one of our production applications and it's great. I see myself using it more now that it's part of the JDK.

Categories