JAXB mappable XML elements - java

In the root.class from my xi-schema, the element item and ohter objects are part of an itemList:
#XmlElementRef(name = "item", namespace = "xi", type = JAXBElement.class, required = false)
//...
protected List<Object> itemList;
I've in the ObjectFactory.class from the main-schema some items as JAXBElements like this:
#XmlElementDecl(namespace = "de-schema", name = "detailedInformation", substitutionHeadNamespace = "xi", substitutionHeadName = "item")
public JAXBElement<numItemType> createDetailedInformation(numItemType num) {
return new JAXBElement<numItemType>(_detailedInformation_QNAME, numItemType.class, null, num);
}
So the numItemType has some attributes and value(num) for the JAXBElement.
NumItemType.class:
#XmlJavaTypeAdapter(numItemTypeAdapter.class)
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "numItemType", namespace = "xi", propOrder = {
"num"
})
public class NumItemType {
#XmlValue
protected BigDecimal num;
#XmlAttribute(name = "precision")
protected String precision;
#XmlAttribute(name = "decimals")
protected String decimals;
//... more Attributes
}
But when JAXB unmarshal the XML document, it will has only elements, for example:
<detailedInformation>
<element1>1234</element1>
<element2>5678</element2>
<element3>bla</element3>
</detailedInformation>
When I marshal it, it should become (like the JAXB java code):
<detailedInformation element2="5678" element3="bla">1234</detailedInformation>
Therefore, I have written an numItemTypeAdapter.class with
NumItemTypeAdapter extends XmlAdapter
AdaptedNum.class:
public class AdaptedNum {
#XmlElement
private double element1;
#XmlElement
private String element2;
#XmlElement
private String element3;
/** Some getter/setter methods */
}
I thought, that would be help me http://blog.bdoughan.com/2012/02/xmlanyelement-and-xmladapter.html, but it is all a bit tricky :-/

It's a bit tricky to sort out exactly where your problem may be occurring. I'm assuming your original model was generated from an XML Schema, this should work as is without any modifications. I've attempted below to provide a scaled down version of your example which may help.
Root
package forum11343610;
import java.util.*;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
#XmlElementRef(name = "item", namespace = "xi", type = JAXBElement.class, required = false)
protected List<Object> itemList = new ArrayList<Object>();
public List<Object> getItemList() {
return itemList;
}
public void setItemList(List<Object> itemList) {
this.itemList = itemList;
}
}
NumItemType
package forum11343610;
import java.math.BigDecimal;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "numItemType", namespace = "xi", propOrder = {
"num"
})
public class NumItemType {
#XmlValue
protected BigDecimal num;
#XmlAttribute(name = "precision")
protected String precision;
#XmlAttribute(name = "decimals")
protected String decimals;
//... more Attributes
}
ObjectFactory
package forum11343610;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
private static final QName _detailedInformation_QNAME = new QName("de-schema", "detailedInformation");
#XmlElementDecl(namespace = "xi", name = "item")
public JAXBElement<NumItemType> createItem(NumItemType num) {
return new JAXBElement<NumItemType>(_detailedInformation_QNAME, NumItemType.class, null, num);
}
#XmlElementDecl(namespace = "de-schema", name = "detailedInformation", substitutionHeadNamespace = "xi", substitutionHeadName = "item")
public JAXBElement<NumItemType> createDetailedInformation(NumItemType num) {
return new JAXBElement<NumItemType>(_detailedInformation_QNAME, NumItemType.class, null, num);
}
}
Demo
package forum11343610;
import java.math.BigDecimal;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class);
ObjectFactory objectFactory = new ObjectFactory();
Root root = new Root();
NumItemType numItemType = new NumItemType();
numItemType.num = BigDecimal.TEN;
numItemType.decimals = "1";
numItemType.precision = "2";
root.getItemList().add(objectFactory.createDetailedInformation(numItemType));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:ns2="de-schema" xmlns:ns3="xi">
<ns2:detailedInformation precision="2" decimals="1">10</ns2:detailedInformation>
</root>

Thank your for your comment.
That's the point:
Demo
NumItemType numItemType = new NumItemType();
numItemType.num = BigDecimal.TEN;
numItemType.decimals = "1";
numItemType.precision = "2";
root.getItemList().add(objectFactory.createDetailedInformation(numItemType));
It should unmarshal and map the XML automatically.
XML Input
<detailedInformation>
<element1>1234</element1>
<element2>5678</element2>
<element3>bla</element3>
</detailedInformation>
With the Code:
Demo
JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class);
Unmarshaller u = jc.createUnmarshaller();
File xml = new File("D:/", "test.xml");
Root root = (Root) u.unmarshal(xml);
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:ns2="de-schema" xmlns:ns3="xi">
<ns2:detailedInformation precision="2" decimals="1">10</ns2:detailedInformation>
</root>
I could parse the XML Document with DOM to a tree and marhalling with JAXB...
Thank you!

In other words:
I want to set new elements to the NumItemType.class for the unmarshalling without change the schema java code.
NumItemType.class
package forum11343610;
import java.math.BigDecimal;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "numItemType", namespace = "xi", propOrder = {
"num"
})
#XmlJavaTypeAdapter(NumItemTypeAdapter.class)
public class NumItemType {
#XmlValue
protected BigDecimal num;
#XmlAttribute(name = "precision")
protected String precision;
#XmlAttribute(name = "decimals")
protected String decimals;
//... more Attributes
}
NumItemTypeAdapter.class
public class NumItemTypeAdapter extends XmlAdapter<AdaptedNum, NumItemType> {
#Override
public NumItemType unmarshal(AdaptedNum an) throws Exception {
NumItemType nit = new NumItemType();
nit.setNum(an.getNum);
nit.setPrecision(an.getPrecision);
nit.setDecimals(an.getDecimals)
return nit;
}
}
AdaptedNum.class
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "adaptedNum", namespace = "", propOrder = {
"element1",
"element2",
"element3"
})
public class AdaptedNum {
#XmlElement(name ="element1")
protected BigDecimal num;
#XmlElement(name ="element2")
private String decimals;
#XmlElement(name ="element3")
private String precison;
// set/get method
}

Related

JAXB Define XML elements with dots

I need to create a XML which matches this structure:
<OfferPackage Name="aaa">
<OfferPackage.Offers>
<OfferCollection Capacity="1">
<Offer Price="12.34"/>
<Offer Price="12.34"/>
</OfferCollection>
</OfferPackage.Offers>
</OfferPackage>
My problem is that I do not know how to achieve this here: <OfferPackage.Offers>. How I can get this "dot notation" with just annotations? All I got out looks like this:
<OfferPackage Name="aaa">
<OfferCollection Capacity="1">
<Offer Price="12.34"/>
<Offer Price="12.34"/>
</OfferCollection>
</OfferPackage>
This is my current code:
#XmlRootElement(name = "OfferPackage")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferPackage {
#XmlAttribute(name = "Name")
private String name = null;
#XmlElement( name = "OfferCollection")
private List<OfferCollection> offers = null;
#SneakyThrows
public String toString() {
var sw = new StringWriter();
var marshaller = JAXBContext
.newInstance(OfferPackage.class)
.createMarshaller();
marshaller.setProperty(JAXB_FRAGMENT, true);
marshaller.marshal(this, sw);
return sw.toString();
}
}
#XmlRootElement(name = "Offer")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferCollection {
#XmlAttribute(name = "Capacity")
private Integer capacity = null;
#XmlElement(name = "Offer")
private List<Offer> offer = null;
}
You can achieve the desired behavior using the #XmlElementWrapper annotation:
Generates a wrapper element around XML representation. This is primarily intended to be used to produce a wrapper XML element around collections.
In your case, it will look similar to this:
#XmlRootElement(name = "OfferPackage")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferPackage {
#XmlAttribute(name = "Name")
private String name = null;
#XmlElementWrapper(name="OfferPackage.Offers")
#XmlElement( name = "OfferCollection")
private List<OfferCollection> offers = null;
#SneakyThrows
public String toString() {
var sw = new StringWriter();
var marshaller = JAXBContext
.newInstance(OfferPackage.class)
.createMarshaller();
marshaller.setProperty(JAXB_FRAGMENT, true);
marshaller.marshal(this, sw);
return sw.toString();
}
}
Other possibility will be to define an intermediate class, OfferPackageOffers to wrap the OfferCollection List::
#XmlRootElement(name = "OfferPackage.Offers")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferPackageOffers {
#XmlElement( name = "OfferCollection")
private List<OfferCollection> offers = null;
//...
}
And use the new class in OfferPackage instead of the mentioned OfferCollection List:
#XmlRootElement(name = "OfferPackage")
#XmlAccessorType(XmlAccessType.FIELD)
public class OfferPackage {
#XmlAttribute(name = "Name")
private String name = null;
#XmlElement( name = "OfferPackage.Offers")
private OfferPackageOffers offers = null;
//...
}

JAXB: Remove parent node keeping it's children

I know it doesn't make much sense, but I have to generate an XML from a Java object without the parent node of some elements, like explained below.
This is the example Java class model for the XML:
#XmlRootElement(name = "person")
public class PersonXml {
#XmlElement(name = "name")
private String name;
#XmlElement(name = "car")
private List<CarXml> cars;
.
#XmlRootElement(name = "car")
public class CarXml {
#XmlElement(name = "model")
private String model;
#XmlElement(name = "brand")
private String brand;
By default, if I generate the XML from an object of PersonXml like this:
StringWriter writer = new StringWriter();
JAXBContext ctx = JAXBContext.newInstance(PersonXml.class);
Marshaller marshaller = ctx.createMarshaller();
marshaller.marshal(xml, writer);
I would get:
<person>
<name>Pedro</name>
<car>
<model>Logan</model>
<brand>Renault</brand>
</car>
<car>
<model>Duster</model>
<brand>Renault</brand>
</car>
</person>
What I need is to remove the <car> tag, or even to prevent it to be generated at all.
I need the XML to be like this:
<person>
<name>Pedro</name>
<model>Logan</model>
<brand>Renault</brand>
<model>Duster</model>
<brand>Renault</brand>
</person>
Of course I could convert the XML to a String and remove the tags with replaceAll or something like this, but I was wondering if there is a nicer way to achieve this.
If you need to generate this output, you can use JAXB as follows:
1) Create a new Person class:
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"field"
})
#XmlRootElement(name = "person")
public class Person {
#XmlElementRefs({
#XmlElementRef(name = "name", type = JAXBElement.class, required = false),
#XmlElementRef(name = "model", type = JAXBElement.class, required = false),
#XmlElementRef(name = "brand", type = JAXBElement.class, required = false)
})
protected List<JAXBElement<String>> field;
public List<JAXBElement<String>> getNameOrModelOrBrand() {
if (field == null) {
field = new ArrayList<>();
}
return this.field;
}
}
2) Create an ObjectFactory to make it easier to use the person class:
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
private final static QName _PersonName_QNAME = new QName("", "name");
private final static QName _PersonModel_QNAME = new QName("", "model");
private final static QName _PersonBrand_QNAME = new QName("", "brand");
public ObjectFactory() {
}
public Person createPerson() {
return new Person();
}
#XmlElementDecl(namespace = "", name = "name", scope = Person.class)
public JAXBElement<String> createPersonName(String value) {
return new JAXBElement<>(_PersonName_QNAME, String.class, Person.class, value);
}
#XmlElementDecl(namespace = "", name = "model", scope = Person.class)
public JAXBElement<String> createPersonModel(String value) {
return new JAXBElement<>(_PersonModel_QNAME, String.class, Person.class, value);
}
#XmlElementDecl(namespace = "", name = "brand", scope = Person.class)
public JAXBElement<String> createPersonBrand(String value) {
return new JAXBElement<>(_PersonBrand_QNAME, String.class, Person.class, value);
}
}
Use the factory as follows:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import java.io.StringWriter;
import java.util.List;
...
ObjectFactory factory = new ObjectFactory();
Person person = factory.createPerson();
List<JAXBElement<String>> list = person.getNameOrModelOrBrand();
list.add(factory.createPersonName("Pedro"));
list.add(factory.createPersonModel("Logan"));
list.add(factory.createPersonBrand("Renault"));
list.add(factory.createPersonModel("Duster"));
list.add(factory.createPersonBrand("Renault"));
JAXBContext ctx = JAXBContext.newInstance(Person.class);
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter writer = new StringWriter();
marshaller.marshal(person, writer);
System.out.println(writer.toString());
The end result is XML as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<name>Pedro</name>
<model>Logan</model>
<brand>Renault</brand>
<model>Duster</model>
<brand>Renault</brand>
</person>
Creating elements in this way is the only way I know to get the end result you need.
There are probably various things you could do to refactor the above code, to streamline the creation of the list of elements - but this shows you the basic approach.
As you already know - this is far from ideal. The end result is not any type of XML that I would want to receive.

Parsing XML Failed

I get the following response XML String after calling a SOAP web service. How can i parse the response back to Java entity so that i can handle the ErrMsg and Status accordingly? I tried with the below code, but keep getting error
Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"NewDataSet"). Expected elements are <{TransactionalSubmissionsSvcs}NewDataSet>
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
Sample Response in String
<NewDataSet>
<SubmissionResult>
<Status>200</Status>
<RefNo>363180319bigKj83i</RefNo>
<ErrMsg>Successful</ErrMsg>
</SubmissionResult>
</NewDataSet>
Sample Client XML Parser
JAXBContext jaxbContext = JAXBContext.newInstance(NewDataSet.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader("Sample Response in String above");
NewDataSet newDataSet = (NewDataSet) jaxbUnmarshaller.unmarshal(reader);
System.out.println(newDataSet.getSubmissionResult());
NewDataSet.java
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"submissionResult"
})
#XmlRootElement(name = "NewDataSet")
public class NewDataSet {
#XmlElement(name = "SubmissionResult", required = true)
protected NewDataSet.SubmissionResult submissionResult;
public NewDataSet.SubmissionResult getSubmissionResult() {
return submissionResult;
}
public void setSubmissionResult(NewDataSet.SubmissionResult value) {
this.submissionResult = value;
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"status",
"refNo",
"errMsg"
})
public static class SubmissionResult {
#XmlElement(name = "Status")
protected short status;
#XmlElement(name = "RefNo", required = true)
protected String refNo;
#XmlElement(name = "ErrMsg", required = true)
protected String errMsg;
public short getStatus() {
return status;
}
public void setStatus(short value) {
this.status = value;
}
public String getRefNo() {
return refNo;
}
public void setRefNo(String value) {
this.refNo = value;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String value) {
this.errMsg = value;
}
}
}
Note: If possible i prefer to use standard java library or external library that is being maintained regularly and up to date.
It looks like you have many NewDataSet classes in your POJO model. Check this line of code JAXBContext.newInstance(NewDataSet.class) and check import whether you imported correct one because exception says that marshaller expects TransactionalSubmissionsSvcs.NewDataSet.
Before edit
You did not mention what the tool do you use. In case it is Jackson you can parse XML payload as below:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.nio.file.Files;
public class XmlMapperApp {
public static void main(String[] args) throws Exception {
String xml = "your xml";
parse(xml);
}
public static void parse(String xml) throws Exception {
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
JsonNode root = xmlMapper.readTree(xml);
JsonNode result = root.at("/SendWithXMLResult");
JsonNode jsonNode = xmlMapper.readTree(result.asText());
JsonNode submissionResult = jsonNode.at("/SubmissionResult");
System.out.println(submissionResult.get("Status"));
System.out.println(submissionResult.get("ErrMsg"));
System.out.println(submissionResult.get("RefNo"));
}
}
If you have prepared POJO model you can deserialise XML directly to it using readValue method.
Found the reason, it was resolved by removing the namespace = "TransactionalSubmissionsSvcs"
#javax.xml.bind.annotation.XmlSchema(namespace = "TransactionalSubmissionsSvcs",elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.mailadapter;
to become
#javax.xml.bind.annotation.XmlSchema(elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.mailadapter;

How to create model class for XML parsing which has iteration of element

I'm beginner JAVA programming. I'm making model class through XML parsing. I know there are some example such as : JAXB, xmapper etc..
I have some xml file which element has iteration. How to create model class for this xml ? Any help..
Let’s map some xml:
<root a="2.2">
<main>
<node1>123</node1>
<node2>123</node2>
</main>
<client value="1" use="true">
<C_node1>aaa</C_node1>
<C_node2>bbb</C_node2>
</client>
<client value="2" use="true">
<C_node1>aaa</C_node1>
<C_node2>bbb</C_node2>
</client>
<client value="3" use="true">
<C_node1>aaa</C_node1>
<C_node2>bbb</C_node2>
</client>
// ...
<client value="100" use="true">
<C_node1>aaa</C_node1>
<C_node2>bbb</C_node2>
</client>
<System>
<DebugFrame>0</DebugFrame>
</System>
</root>
I found http://docs.oracle.com/cd/E12840_01/wls/docs103/webserv/data_types.html. Is that what I want ?
Edited
Here is real code. I have some compile error. Java version is
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)
Here is error message ;
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
Class has two properties of the same name "mode"
this problem is related to the following location:
at public java.lang.String xmlParserTest.RootTest.getMode()
at xmlParserTest.RootTest
this problem is related to the following location:
at private java.lang.String xmlParserTest.RootTest.mode
at xmlParserTest.RootTest
Class has two properties of the same name "inputFile"
this problem is related to the following location:
at public java.lang.String xmlParserTest.MainEntity.getInputFile()
at xmlParserTest.MainEntity
at private xmlParserTest.MainEntity xmlParserTest.RootTest.main
at xmlParserTest.RootTest
this problem is related to the following location:
at private java.lang.String xmlParserTest.MainEntity.inputFile
at xmlParserTest.MainEntity
at private xmlParserTest.MainEntity xmlParserTest.RootTest.main
at xmlParserTest.RootTest
: console.java
package xmlParserTest;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class console {
public static void main(String[] args) {
try
{
JAXBContext jc = JAXBContext.newInstance(RootTest.class);
Unmarshaller u = jc.createUnmarshaller();
File f = new File("Testing.xml");
RootTest product = (RootTest) u.unmarshal(f);
System.out.println(product.getMode());
System.out.println(product.getMainEntity().getInputFile());
System.out.println(product.getMainEntity().getOutputFolder());
}catch (JAXBException e) {
e.printStackTrace();
}
}
}
: RootTest.java
package xmlParserTest;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Function")
public class RootTest {
private MainEntity main;
private String mode;
#XmlElement(name="Main")
public MainEntity getMainEntity() {
return main;
}
public void setMainEntity(MainEntity _main) {
this.main = _main;
}
#XmlAttribute(name="mode")
public String getMode() {
return mode;
}
public void setMode(String _mode) {
this.mode = _mode;
}
public RootTest()
{
}
}
: MainEntity.java
package xmlParserTest;
import javax.xml.bind.annotation.XmlElement;
public class MainEntity {
private String inputFile;
private String inputType;
private String outputFolder;
private String outputType;
#XmlElement(name="InputFile")
public String getInputFile() {
return inputFile;
}
public void setInputFile(String _inputFile) {
this.inputFile = _inputFile;
}
public String getInputType() {
return inputType;
}
public void setInputType(String _type) {
this.inputType = _type;
}
#XmlElement(name="OutputFolder")
public String getOutputFolder() {
return outputFolder;
}
public void setOutputFolder(String _outputFolder) {
this.outputFolder = _outputFolder;
}
public String getOutputType() {
return outputType;
}
public void setOutputType(String _type) {
this.outputType = _type;
}
public MainEntity()
{
}
}
: Testing.xml
<?xml version="1.0" encoding="UTF-8"?>
<Function mode="Execute">
<Main>
<InputFile type="string">C:\DATA\test.txt</InputFile>
<OutputFolder type="string">C:\Test</OutputFolder>
</Main>
</Function>
If You wnat to use JAXB, first of all, You need to create main model, that looks like this:
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private MainEntity main;
#XmlElement(name = "client")
private List<ClientEntity> clients;
#XmlAttribute
private String a;
#XmlElement(name = "System")
private SystemEntity system;
//getters and setters for all fields
}
Then, specify entities:
public class MainEntity {
private String node1;
private String node2;
//getters and setters for all fields
}
#XmlAccessorType(XmlAccessType.FIELD)
public class ClientEntity {
#XmlElement(name = "C_node1")
private String C_node1;
#XmlElement(name = "C_node2")
private String C_node2;
#XmlAttribute
private Long value;
#XmlAttribute
private boolean use;
//getters and setters for all fields
}
#XmlAccessorType(XmlAccessType.FIELD)
public class SystemEntity {
#XmlElement(name = "DebugFrame")
private Long debugFrame;
//getters and setters for all fields
}
As You see, we use #XmlElement(name = "System") to set alias for field and #XmlAttribute to read field from attribute.
To unmarshall XML with JAXB, create context for your class model:
JAXBContext context = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(file);
Don't forget: when You create model, You need to specify getters and setters for fields that You want to marshall/unmarshall and also specify non-argument constructor for class.
More about annotations You can find here:
http://www.techferry.com/articles/jaxb-annotations.html
Have fun!:)
With JAXB, you can create the required Java classes as below:
#XmlRootElement(name = "main")
public class Main {
String node1;
String node1;
//getters and setters for fields
}
#XmlRootElement(name = "client")
public class Client {
String node1;
String node1;
#XmlAttribute
private boolean use;
#XmlAttribute
private int value;
//getters and setters for fields
}
And then create a Root class to represent your XML file:
#XmlRootElement(name = "root")
public class Root {
//add a list of client instances
#XmlElement(name = "client")
private List<Client> clientList;
//add an instance of main
#XmlElement(name = "main")
private Main main;
// setters to set the values for main and clients
}
Now, with these lines of code you can create the XML representation for the Root class:
Root root = new Root();
root.setMain(CREATE_AND_SET_AN_INSTANCE_OF_MAIN);
root.setClientList(CREATE_AND_SET_A_LIST_OF_CLIENTS);
String filePath = "PATH_TO_SAVE_YOUR_FILE";
File file = new File(filePath);
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(alpha, file);
And you can use these lines of code to read the XML back to Java object:
String filePath = "XML_FILE_PATH";
File file = new File(filePath);
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Root root = (Root) jaxbUnmarshaller.unmarshal(file);
Ref: Java Architecture for XML Binding (JAXB)

how to get XmlElement of unmarshaled java object

#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Item", propOrder = {
"code",
"name",
"price"
})
#XmlRootElement(name="inventory")
public class Item {
#XmlElement(name="catalog_num", required = true)
protected String code;
#XmlElement(name="catalog_descrip", required = true)
protected String name;
#XmlElement(name="prod_price")
protected double price;
public String getCode() {
return code;
}
JAXBContext databaseJC = JAXBContext.newInstance(Item.class);
Unmarshaller databaseUnmarshaller = databaseJC.createUnmarshaller();
File databaseXML = new File("src/forum6838882/database.xml");
Item item = (Item) databaseUnmarshaller.unmarshal(databaseXML);
My question is:
How could I get the #XmlElement(name="catalog_num", required = true) from item object. I need know the name="catalog_num" here.
JAXB (JSR-222) does not provide an API to introspect the metadata. You can however use the Java Reflection APIs (java.lang.reflect) to get the annotations and examine them yourself.
Demo
import java.lang.reflect.*;
import javax.xml.bind.annotation.*;
public class Demo {
public static void main(String[] args) throws Exception {
Field field = Item.class.getDeclaredField("code");
XmlElement xmlElement = field.getAnnotation(XmlElement.class);
System.out.println(xmlElement.name());
}
}
Output
catalog_num

Categories

Resources