javax.xml.bind.UnmarshalException: unexpected element (uri:"" - java

I am getting an exception while turning an XML response from a service to a POJO. The XML looks like this:
Here is my XML response.
javax.xml.bind.UnmarshalException: unexpected element (uri:""
, local:"ItemSearchResponse"). Expected elements are
<{http://webservices.amazon.com/AWSECommerceService/2011-08-01}ItemSearchResponse>
I am using it like this:
Document response = getResponse(url);
JAXBContext context = JAXBContext.newInstance(AmazonItem.class);
Unmarshaller unMarshaller = context.createUnmarshaller();
newItem = (AmazonItem) unMarshaller.unmarshal(response);
Below are the details of my files
package-info.java
#XmlSchema(
namespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.services.amazon;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
AmazonItem.java
#XmlRootElement(name="ItemSearchResponse")
#XmlAccessorType(XmlAccessType.FIELD)
public class AmazonItem
{
#XmlElement(name="Items")
private Items items = null;
}
Items.java
#XmlAccessorType(XmlAccessType.FIELD)
public class Items {
#XmlElement(name="Item")
List<Item> items = new ArrayList();
}
Item.java
#XmlAccessorType(XmlAccessType.FIELD)
public class Item {
#XmlElement(name="ASIN")
private String asin;
#XmlElement(name="ItemAttributes")
private ItemAttributes attributes;
#XmlElement(name="ItemLinks")
private List<ItemLinks> itemLinks;
}
ItemAttributes.java
#XmlAccessorType(XmlAccessType.FIELD)
public class ItemAttributes {
#XmlElement(name="Title")
private String title;
#XmlElement(name="Actor")
private List<String> actor;
#XmlElement(name="ProductGroup")
private String productGroup;
}
ItemLink.java
#XmlAccessorType(XmlAccessType.FIELD)
public class ItemLink {
#XmlElement(name="Description")
private String description;
#XmlElement(name="URL")
private String url;
}
ItemLinks.java
#XmlAccessorType(XmlAccessType.FIELD)
public class ItemLinks {
#XmlElement(name="ItemLink")
List<ItemLink> itemLinks;
}

The error message is saying that you are getting an XML document that looks like this:
<ItemSearchResponse>
Instead of one like the following that matches the namespace qualification that you have mapped:
<ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">

The explanation is here:
The JAXBContext instance is intialized with class(es) passed as parameter(s) and classes that are statically reachable from these class(es).
Initialize JAXBContext using package, so it can see #XmlSchema declared in package-info.java:
JAXBContext.newInstance("com.services.amazon")

If you're using DocumentBuilderFactory in your getResponse method, try setting namespace awareness:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
I had the same UnmarshalException and this solved it.

Remove the namespace from package-info.java and change
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED
to
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED.

Remove the namespace from package-info.java
It's work for me
Ex:
#javax.xml.bind.annotation.XmlSchema(namespace = "", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)

Related

XML parser (Unmarshall) using JaxB to get elemet from xml file

I new to jaxB XML parser. i need to get the all the attribute (idref, type, name, scope) from element tag ** I tried something but getting error.
XML File
<?xml version="1.0" encoding="windows-1252"?>
<xmi:XMIxmi:version="2.1"xmlns:uml="http://www.omg.org/spec/UML/20090901"xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:thecustomprofile="http://www.sparxsystems.com/profiles/thecustomprofile/1.0" xmlns:SysML="http://www.omg.org/spec/SysML/20161101/SysML">
<xmi:Documentation exporter="Enterprise Architect" exporterVersion="6.5" exporterID="1555"/>
<xmi:Extension extender="Enterprise Architect" extenderID="6.5">
<elements>
<element xmi:idref="EAPK_5560E5AF_736A_4703_AC79_CA3FAA60984B" xmi:type="uml:Package" name="PackageView" scope="public"></element>
<element xmi:idref="EAPK_59058493_9220_4b05_888A_67C6854C97EC" xmi:type="uml:Package" name="Read from Communication Interface" scope="public">
</element>
<element xmi:idref="EAID_870B8E54_0FF2_4a90_A9C1_23F477DF695F" xmi:type="uml:Activity" name="Read from communication interface" scope="public">
</element>
</elements>
</xmi:Extension>
</xmi:XMI>
Main Class
public class XmlElement {
public static void main(String[] args) {
JAXBContext jaxbContext;
String fileLocation = "C:\\vinoth\\XML_JaxbParser\\elements.xml";
try (FileInputStream fileInputStream = new FileInputStream(fileLocation)) {
System.out.println("******** PARSING START ********");
jaxbContext = JAXBContext.newInstance(Xmi.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
elements elements = (elements) unmarshaller.unmarshal(fileInputStream);
System.out.println(elements);
System.out.println("******** PARSING DONE ********");
} catch (Exception e) {
System.out.println("******** ERROR: SOMETHING WENT WRONG ********");
e.printStackTrace();
}
}
}
elements.java
#XmlRootElement(name = "xmi")
#XmlAccessorType(XmlAccessType.FIELD)
public class Elements {
#XmlElement(name = "elements")
private List<Elements> elements;
// Generate Getters and Setters...
#Override
public String toString() {
return "Elements [elements="+ elements +"]";
}
}
element.java
#XmlAccessorType(XmlAccessType.FIELD)
public class Element {
#XmlAttribute(name = "idref")
private String idref;
#XmlAttribute(name = "type")
private String type;
#XmlAttribute(name = "name")
private String name;
#XmlAttribute(name = "scope")
private String scope;
//Generate Getters and Setters...
#Override
public String toString() {
return "Element [idref=" + idref + ",type=" + type + ", name=" + name + ", scope=" + scope+ "]";
}
}
I need to get the the element attribute from the given XML file. I don't know where I made a mistake. Root element and parent and children, i can understand mistake from mapping section. but I couldn't sort out.
Your XML file uses many different XML namespaces,
which you need to consider in your Java code.
Especially notice, that the namespace URIs (e.g.
"http://schema.omg.org/spec/XMI/2.1") are the
only relevant thing. The namespace prefixes (e.g. xmi:) are not
relevant for Java. They were only invented to make the XML
easier to read for humans.
I recommend to define all your XML namespace URIs as Java
string contants to avoid typing them many times in your code:
public class NameSpaces {
public final static String UML = "http://www.omg.org/spec/UML/20090901";
public final static String XMI = "http://schema.omg.org/spec/XMI/2.1";
public final static String THE_CUSTOM_PROFILE = "http://www.sparxsystems.com/profiles/thecustomprofile/1.0";
public final static String SYSML = "http://www.omg.org/spec/SysML/20161101/SysML";
}
You need to carefully look at your XML content (XML elements
XMI, Documentation, Extension, Elements, Element and
their XML attributes) to see which XML namespace is used where.
Then in all your Java classes you need to specify the right
namespace in the #XmlAttribute and #XmlElement annotations.
You will also need to specify a namespace in the #XmlRootElement
annotation of your root class.
See also the Javadoc of the JAXB annotations.
I will not do all your work for you, but instead only show how
your root class and the Element class may look like.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "XMI", namespace = NameSpaces.XMI)
public class XMI {
#XmlAttribute(name = "version", namespace = NameSpaces.XMI)
private String version;
#XmlElement(name = "Documentation", namespace = NameSpaces.XMI)
private Documentation documentation;
#XmlElement(name = "Extension", namespace = NameSpaces.XMI)
private Extension extension;
// Getters, setters, toString omitted here for brevity
}
#XmlAccessorType(XmlAccessType.FIELD)
public class Element {
#XmlAttribute(name = "idref", namespace = NameSpaces.XMI)
private String idref;
#XmlAttribute(name = "type", namespace = NameSpaces.XMI)
private String type;
#XmlAttribute(name = "name")
private String name;
#XmlAttribute(name = "scope")
private String scope;
// Getters, setters, toString omitted here for brevity
}

Jaxb and namespace of inner element

I met a problem that looks simple but not obvious to solve.
I have 2 packages with classes marshalled to xml with different namespaces. One class is container for others.
package namespace1;
#XmlRootElement(name = "container", namespace = "urn:nmsp:container:001.02")
#XmlAccessorType(XmlAccessType.FIELD)
#Getter
#Setter
public class Container {
#XmlElement(name = "name")
private String name;
#XmlElement(name = "messages")
private List<Message> messages;
}
-------------------------------------------
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Message", propOrder = {
"document"
})
public class Message {
#XmlElement(name = "Document", namespace = "urn:iso:std:iso:20022:001", required = true)
protected Document document;
}
-------------------------------------------
package-info.java
#javax.xml.bind.annotation.XmlSchema(namespace = "urn:nmsp:container:001.02",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(namespaceURI = "urn:nmsp:container:001.02", prefix = "")
})
package namespace1;
and
package namespace2;
#XmlRootElement(name = "document", namespace = "urn:iso:std:iso:20022:001")
#XmlAccessorType(XmlAccessType.FIELD)
public class Document {
#XmlElement(name = "id")
private String id;
}
package-info.java
#javax.xml.bind.annotation.XmlSchema(namespace = "urn:iso:std:iso:20022:001",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(namespaceURI = "urn:iso:std:iso:20022:001", prefix = "")
})
package namespace2;
What I would like to get is:
<container xmlns="urn:nmsp:container:001.02">
<name>Hello</name>
<messages>
<Document xmlns="urn:iso:std:iso:20022:001">
<id>ID1</id>
</Document>
</messages>
</container>
But what I get is:
<container xmlns="urn:nmsp:container:001.02" xmlns:ns2="urn:iso:std:iso:20022:001">
<name>Hello</name>
<messages>
<ns2:Document>
<ns2:id>ID1</ns2:id>
</ns2:Document>
</messages>
</container>
Marshalling code is:
Container conxml = new Container("Hello");
conxml.setMessages(List.of(new Message(new Document("ID1")))));
JAXBContext jc = JAXBContext.newInstance(Container.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter writer = new StringWriter();
QName _Conxml_QNAME = new QName("urn:nmsp:container:001.02", "container");
JAXBElement<Container> conxmlJAXBElement = new JAXBElement<>(_Conxml_QNAME, Container.class, null, conxml);
marshaller.marshal(conxmlJAXBElement, writer);
System.out.println(writer.toString());
Almost all solutions suggest to fix it with package-info.java but it doesn't help practically.
Can you please give me a hint where I am doing it wrong?
The link to maven project: JaxbTest.7z
The two XML files you give are equivalent, your choice of namespace declaration is a question of taste. The prefixes you set in the #XmlNs annotations are taken into account, when choosing the prefix for each namespace. However, JAXB RI at least, does not redefine them mid-document.
If you want to more directly intervene in the way the XML is generated, you need to add additional components between JAXB and the Writer. E.g. you can use StAX and marshall your document to an XMLStreamWriter like this one (the IndentingXMLStreamWriter comes from TXW2, a dependency of JAXB RI):
private static class RedefineNsXmlStreamWriter extends IndentingXMLStreamWriter {
#Override
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
final String known_prefix = getNamespaceContext().getPrefix(namespaceURI);
super.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, localName, namespaceURI);
if (!XMLConstants.DEFAULT_NS_PREFIX.equals(known_prefix)) {
super.writeNamespace(XMLConstants.DEFAULT_NS_PREFIX, namespaceURI);
}
}
#Override
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
// Ignore it
}
public RedefineNsXmlStreamWriter(XMLStreamWriter out) {
super(out);
}
}
Then you create an XMLStreamWriter capable of writing to the Writer and serialize:
final XMLStreamWriter xmlWriter = new RedefineNsXmlStreamWriter(XMLOutputFactory.newFactory()//
.createXMLStreamWriter(writerCont));
marshallerCont.marshal(conxmlJAXBElement, xmlWriter);
Of course the RedefineNsXmlStreamWriter get more complicated once you take into account all cases, but it works for your example.

XML to Java JaxB

My attempt to convert an XML to Java using JAXB not working as expected. There are multiple other similar questions around it but none of the suggested solutions I looked into seem to help me.
Below is my bean
#XmlRootElement(name = "ListingResponse", namespace = "http://www.random.com")
#XmlType(propOrder = {"success", "listingId", "description"})
public class ListingResponse {
private String success;
private String listingId;
private String description;
public String getSuccess() {
return success;
}
#XmlElement(name = "Success")
public void setSuccess(String success) {
this.success = success;
}
public String getListingId() {
return listingId;
}
#XmlElement(name = "ListingId")
public void setListingId(String listingId) {
this.listingId = listingId;
}
public String getDescription() {
return description;
}
#XmlElement(name = "Description")
public void setDescription(String description) {
this.description = description;
}
Below is my attempt to do the unmarshaling
ListingResponse response = null;
try {
JAXBContext jaxbContext = JAXBContext.newInstance(ListingResponse.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
response = (ListingResponse) jaxbUnmarshaller.unmarshal(new File("response.xml"));
} catch (JAXBException e) {
e.printStackTrace();
}
And finally my response.xml content
<ListingResponse xmlns="http://www.random.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Success>true</Success>
<Description>ListingId 123 created.</Description>
<ListingId>123</ListingId>
</ListingResponse>
There are not exceptions being thrown.
'response' is NOT null.
I have tried adding #XmlAccessorType(XmlAccessType.FIELD / PROPERTY)
with #XMLEelement annotation on the fields/ set methods but that didn't seem to help either.
However, response is always 'empty' with none of the fields initialized.
Can you guys spot the issue here?
Currently you only have specified the correct namespace qualification for the root element. You need to use the package level #XmlSchema annotation to map the namespace qualification for your model.
package-info.java
#XmlSchema(
namespace = "http://www.random.com",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html

Getting incorrect values while converting an XML into a Java Object

I m trying to convert XML file into Java Object using Jaxb unmarshalling.
public static void main(String[] args) {
String input = "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">"+
" <key>1</key>" +
"<income>100.335</income>" +
"</project>" ;
NexusClient c1 = new NexusClient();
c1.getObject(input);
}
/*********/
public boolean getObject(String input) {
InputSource inputSource = new InputSource(new StringReader(input));
System.out.println(inputSource);
try {
JAXBContext jaxbContext = JAXBContext
.newInstance(mavenEntity.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
mavenEntity mavenObject = (mavenEntity) jaxbUnmarshaller
.unmarshal(inputSource);
System.out.println("Success"+mavenObject.getIncome());
} catch (JAXBException e) {
System.out.println("Unable to parse the XML Context");
e.printStackTrace();
return false;
}
return true;
}
I m facing an issue while trying to extract "Income" tag information. I couldn't extract correct values using Jaxb. My pojo class is :
#XmlRootElement(name = "project", namespace = "http://maven.apache.org/POM/4.0.0")
#XmlAccessorType(XmlAccessType.FIELD)
public class mavenEntity {
#XmlElement(name = "key", type = String.class)
private String key;
#XmlElement(name = "income", type = String.class)
private String income;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getIncome() {
return income;
}
public void setIncome(String income) {
this.income = income;
}
}
I m getting Null as output for any tag in XML. I guess there is some problem with my name space in XML Annotation. But I really don't understand what it is. Before posting this, I did some groundwork by referring to few links similar to this But still my result is incorrect. Can some one help me out.
The namespace qualification in your model does not match the document. Instead of specifying the namespace on #XmlRootElement and all instances of #XmlElement you can specify the namespace qualification at the package level using #XmlSchema.
package-info.java
#XmlSchema(
namespace = "http://maven.apache.org/POM/4.0.0",
elementFormDefault = XmlNsForm.QUALIFIED)
package org.example.foo;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
mavenEntity.java
I have removed the unnecessary annotations from this class (see: http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html).
package org.example.foo;
import javax.xml.bind.annotation.XmlSchema;
#XmlRootElement(name = "project")
#XmlAccessorType(XmlAccessType.FIELD)
public class mavenEntity {
private String key;
private String income;
}
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
You will need to add namespace to your #XmlElement annotated fields too
#XmlElement(name = "key", namespace = "http://maven.apache.org/POM/4.0.0")
private String key;
#XmlElement(name = "income", namespace = "http://maven.apache.org/POM/4.0.0")
private String income;
That's because your root element has a particular namespace. Since the nested elements don't have namespace prefix, they are using the root's. I guess this is required by JAXB.
Some alternatives and/or explanations here and here.

JAXB - empty tags with no xsi:nil

I have a String property in an object annotated as follows:
#XmlElement(name = "Item", required = true, nillable = true)
private String item;
The result after marshaling is
<Item xsi:nil="true"/>
while I would like it to be
<Item/>
since the third-party service accepting my XML messages wants it like the latter case. I am using jaxb2. Does anyone knows how I could possibly do this?
Thanks a lot
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
The following example requires the use of MOXy as the JAXB provider. This is because the JAXB RI does not call the XmlAdapter when the field/property is null. For information on specifying MOXy as your JAXB provider see:
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
StringAdapter
The XmlAdapter will convert the String value to an object with a property annotated with #XmlValue.
package forum8986842;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class StringAdapter extends XmlAdapter<StringAdapter.AdaptedString, String>{
#Override
public String unmarshal(AdaptedString adaptedString) throws Exception {
if(null == adaptedString) {
return null;
}
String string = adaptedString.value;
if("".equals(string)) {
return null;
}
return string;
}
#Override
public AdaptedString marshal(String string) throws Exception {
AdaptedString adaptedString = new AdaptedString();
adaptedString.value = string;
return adaptedString;
}
public static class AdaptedString {
#XmlValue public String value;
}
}
Root
The #XmlJavaTypeAdapter annotation is used to specify the XmlAdapter:
package forum8986842;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement(name="Root")
public class Root {
private String item;
#XmlElement(name = "Item", required = true, nillable = true)
#XmlJavaTypeAdapter(StringAdapter.class)
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
}
Demo
The following code can be used to demonstrate the above mapping. Two documents are used one with an empty Item element, and the other with a populated Item element.
package forum8986842;
import java.io.StringReader;
import javax.xml.bind.*;
public class Demo {
private JAXBContext jc;
public Demo() throws JAXBException {
jc = JAXBContext.newInstance(Root.class);
}
public static void main(String[] args) throws Exception {
Demo demo = new Demo();
demo.demo("<Root><Item/></Root>");
demo.demo("<Root><Item>Hello World</Item></Root>");
}
private void demo(String xml) throws JAXBException {
System.out.println("\n\nINPUT: " + xml);
StringReader stringReader = new StringReader(xml);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(stringReader);
System.out.println("ITEM: " + root.getItem());
System.out.print("OUTPUT: ");
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.marshal(root, System.out);
}
}
Output
The following is the output from running the demo code:
INPUT: <Root><Item/></Root>
ITEM: null
OUTPUT: <Root><Item/></Root>
INPUT: <Root><Item>Hello World</Item></Root>
ITEM: Hello World
OUTPUT: <Root><Item>Hello World</Item></Root>
For More Information
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html
http://blog.bdoughan.com/search/label/XmlAdapter
I found changing the xsd was easier
<xs:element name="name">
<xs:complexType/>
</xs:element>
and in your code, when you auto generate your java src/classes
you would specify new Name and set the Name to whichever object name belongs under

Categories