Wrap XML elements in a sub-element with JAXB/JAX-RS - java

I have the following class which shall be serialized/deserialized to XML.
#XmlRootElement(name = "nnxml")
#XmlAccessorType(XmlAccessType.FIELD)
public class InfoRequest {
#XmlElement(name = "vendor_id")
private String vendorId;
#XmlElement(name = "vendor_authcode")
private String authCode;
}
This currently gives me this XML which is consistent and correct:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nnxml>
<vendor_id>vendor id</vendor_id>
<vendor_authcode>auth code</vendor_authcode>
</nnxml>
However I need to wrap the XML elements in another element like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nnxml>
<info_request>
<vendor_id>vendor id</vendor_id>
<vendor_authcode>auth code</vendor_authcode>
</info_request>
</nnxml>
How can I wrap the above fields in a info_request element? Do I have to create something like an inner class or is there a simpler approach?

One approach is to create a Wrapper class like this and to insert your class
#XmlRootElement(name = "nnxml")
#XmlAccessorType(XmlAccessType.FIELD)
public class Nnxml implements Serializable {
#XmlElement(name = "info_request")
private InfoRequest request;
}
The annotations of subclass are optional
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "info_request", propOrder = {
"vendorId",
"authCode"
})
class InfoRequest implements Serializable{
#XmlElement(name = "vendor_id")
private String vendorId;
#XmlElement(name = "vendor_authcode")
private String authCode;
}
Output is
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nnxml>
<info_request>
<vendor_id>vendor id</vendor_id>
<vendor_authcode>auth code</vendor_authcode>
</info_request>
</nnxml>

Related

JaxB: Not workoing for XML child tag with capital letter

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<InstanceTree xmlns="http://www.testsite.org/Schemas/xyzSchema">
<Instance id="inst0" depth="1">
<UserData type="Instance">
<userValue title="occurrenceUUID" value="abc/>
</UserData>
<UserData type="Part" name="pqr">
<UserValue title="PartNumber" value="MTG_238_ZB_LACKIERUNG" />
</UserData>
</Instance>
</InstanceTree>
#XmlRootElement(name = "InstanceTree")
public class InstanceTree {
}
#XmlRootElement(name = "Instance")
public class Instance {
private List<Userdata> userdata;
#XmlElement
public List<Userdata> getUserdata() {
return userdata;
}
}
#XmlRootElement(name = "UserValue")
public class UserValue {
private List<UserValue> userValue;
#XmlElement
public List<UserValue> getUserValue() {
return userValue;
}
}
#XmlRootElement(name = "UserData")
public class Userdata {
}
In xml giving NullPointerException for upper case Instance, UserData, UserValue.
Giving error for xmlns="http://www.testsite.org/Schemas/abcSchema". working fine after removing url.
Use #XmlElement(name="Userdata") otherwise jaxb uses the attribute name.
#XmlRootElement(name = "Instance")
public class Instance {
private List<Userdata> userdata;
#XmlElement(name = "Userdata")
public List<Userdata> getUserdata() {
return userdata;
}
}
use also package-info.java
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://www.testsite.org/Schemas/abcSchema",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
#javax.xml.bind.annotation.XmlNs(prefix = "", namespaceURI = "http://www.testsite.org/Schemas/abcSchema")
}
)
package com.your.package;

how to add java jaxb marshaller meta-data to root element only?

i have the following code
#XmlAccessorType (XmlAccessType.FIELD)
private static class MyAttribute<T> {
private String name;
#XmlElement(name = "value")
private T value;
}
#XmlRootElement(name = "duke-eport")
#XmlAccessorType (XmlAccessType.FIELD)
public class DukeDBInfo {
#XmlElement(name = "sys-attribute")
private List<MyAttribute<?>> sysAttribute;
}
when using jaxb marshaller with it i get the following output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<duke-eport>
<sys-attribute>
<name>username</name>
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">udsds</value>
</sys-attribute>
<sys-attribute>
<name>ip</name>
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">127.0.0.1</value>
</sys-attribute>
<sys-attribute>
<name>server-date</name>
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:dateTime">2015-05-19T16:23:09.595+03:00</value>
</sys-attribute>
how can i remove the xmlns:xsi and the xml:xs from each and add it only once to the root node ?
import org.w3._2001.xmlschema.Adapter1;
#XmlAccessorType (XmlAccessType.FIELD)
#XmlType(name = "myAttribute", propOrder = {
"username",
"server-date"
})
private static class MyAttribute<T> {
protected String username;
#XmlElement(type = String.class)
#XmlJavaTypeAdapter(Adapter1 .class)
#XmlSchemaType(name = "dateTime")
protected Calendar server-date;
#XmlElement(username = "value")
private T value;
}
#XmlRootElement(username = "duke-eport")
#XmlAccessorType (XmlAccessType.FIELD)
public class DukeDBInfo {
#XmlElement(username = "sys-attribute")
private List<MyAttribute<?>> sysAttribute;
}

How to ignore a field from binding to XML with JAXB

I have a simple class that looks like this
import nl.hu.pf.coproco.model.Observeable;
#XmlRootElement (name = "Purpose")
#XmlAccessorType (XmlAccessType.FIELD)
public class Purpose implements Observeable{
private String name;
private ArrayList<Observer> observers;
#XmlElement (name = "subPurpose")
private ArrayList<Purpose> subPurposes;
//methods
}
But Observable is an interface so I get an exception because JAXB can'ty handle interfaces. I tried figuring out how to ignore the field with the ArrayList<Observer> so it wont be exported to xml.
I tried using the #XmlTransient annotation but the I get the following eception javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"purpose"). Expected elements are <{}Purpose>
This happens when Unmarshalling but I want to Marshall that class too
Sample xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<purpose>
<name>All Purposes</name>
<subPurpose>
<name>Creational</name>
</subPurpose>
<subPurpose>
<name>Structural</name>
</subPurpose>
<subPurpose>
<name>Behavioral</name>
<subPurpose>
<name>Behavioral 1</name>
</subPurpose>
<subPurpose>
<name>Behavioral 2</name>
</subPurpose>
</subPurpose>
</purpose>
The interface Observable looks like this:
public interface Observeable {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers(Object o, String arg);
}
Your xml contains purpose not Purpose so change #XmlRootElement(name = "Purpose") to
#XmlRootElement(name = "purpose")
And add #XmlTransient on observers like this
#XmlTransient
private ArrayList<Observer> observers;

Unmarshalling with complex type

I'm having trouble unmarshalling XML that represents an invoice in this form:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<Response xmlns="Lamp">
<Result>
<Title>The Title</Title>
<Lines>
<anyType xsi:type="InvoiceLine">
<Name>Name One</Name>
<Quantity>1.0000</Quantity>
</anyType>
<anyType xsi:type="InvoiceLine">
<Name>Name Two</Name>
<Quantity>2.0000</Quantity>
</anyType>
</Lines>
</Result>
</Response>
</soap:Body>
</soap:Envelope>
The Invoice class:
#XmlAccessorType(XmlAccessType.FIELD)
public class Invoice {
public String Title;
public List<InvoiceLine> Lines;
}
The InvoiceLine class:
#XmlAccessorType(XmlAccessType.FIELD)
public class InvoiceLine extends anyType {
public String Name;
public float quantity;
}
And a abstract class for anyType:
public abstract class anyType {}
This is the code I'm using to do the unmarshalling:
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("input.xml");
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(is);
xsr.nextTag();
while(!xsr.getLocalName().equals("Result")) {
xsr.nextTag();
}
JAXBContext jc = JAXBContext.newInstance(Invoice.class, InvoiceLine.class);
javax.xml.bind.Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Invoice> jb = unmarshaller.unmarshal(xsr, Invoice.class);
xsr.close();
System.out.println(jb.getValue());
}
The problem is the Lines list only contains 1 entry with Name=null and quantity=0.0.
-- Edit:
I've just tried adding XmlElement and XmlElementWrapper annotations to both classes, the only change is that the Lines list has no elements.
Modified Invoice:
#XmlAccessorType(XmlAccessType.FIELD)
public class Invoice {
#XmlElement(name = "Title")
public String Title;
#XmlElement(name = "anyType")
#XmlElementWrapper(name = "Lines")
public List<InvoiceLine> Lines;
}
Modified InvoiceLine:
#XmlAccessorType(XmlAccessType.FIELD)
public class InvoiceLine extends anyType {
#XmlElement(name = "Name")
public String Name;
#XmlElement(name = "Quantity")
public float Quantity;
}
-- Edit:
I've just tried making the attributes lower case, but still no luck.

Nested elements with JAXB where element holds attribute and element value at the same time

Environment: JAXB 2.1.2 with EclipseLink MOXy
Requirement:
I would like to get such an XML when marshalled:
<?xml version="1.0" encoding="UTF-8"?>
<root id="id123">
<email>test#gmail.com</email>
<address type="short">...</address>
</root>
I model this with these two classes:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="root")
public class ClassA {
#XmlAttribute(name="id")
private String id = null;
#XmlElement(name="address")
private Address addr = new Address();
// and some getters setters
}
and
#XmlAccessorType(XmlAccessType.FIELD)
public class Address {
#XmlElement(name="address")
private String address = null;
#XmlAttribute(name="type")
private String type = null;
}
What I get is this, where address gets nested twice:
<?xml version="1.0" encoding="UTF-8"?>
<root id="id123">
<email>test#gmail.com</email>
<address type="short">
<address>...</address>
</address>
</root>
How can I remove one hierarchy?
You could do the following leveraging #XmlValue:
#XmlAccessorType(XmlAccessType.FIELD)
public class Address {
#XmlValue
private String address = null;
#XmlAttribute(name="type")
private String type = null;
}
For More Information
http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html

Categories