I have the following XML file to unmarshall
<root>
<emp>Google</emp>
<emp>Yahoo</emp>
<xyz>random</xyz>
</root>
And i have used annotations in the following way,
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp")
private String emp1;
#XmlElement(name = "emp")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
My problem is while i'm trying to get
obj.getEmp1(); // result is Yahoo instead of Google
obj.getEmp2(); // result is null.
Kindly clarify me, what am i doing wrong?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
The standard JAXB (JSR-222) annotations do not support mapping 2 different properties to the same XML element.
You could use EclipseLink JAXB (MOXy)'s #XmlPath extension for this use case.
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlPath("emp[1]/text()")
private String emp1;
#XmlPath("emp[2]/text()")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
If for whatever reason you cannot use MOXy, another solution would be to map the emp element as a list
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp")
private List<String> emp;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
And then use the following code to get the values:
obj.getEmp().get(0);
obj.getEmp().get(1);
But Blaise's solution is more elegant
You could have a String[] field and have your current accessor methods access the String[].
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
private String[] emp = new String[2];
private String xyz;
public String getEmp1() {
return emp[0];
}
public void setEmp1(String emp1) {
this.emp[0] = emp1;
}
public String getEmp2() {
return emp[1];
}
public void setEmp2(String emp2) {
this.emp[1] = emp2;
}
public String getXyz() {
return xyz;
}
public void setXyz(String xyz) {
this.xyz = xyz;
}
}
This might work.
<root>
<emp1>Google</emp1>
<emp2>Yahoo</emp2>
<xyz>random</xyz>
</root>
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp1")
private String emp1;
#XmlElement(name = "emp2")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
}
Related
I have XML configuration that I must unmarshal with JAXB and then use this objects in java code. I have one parent object "tags" and two child tags "innerTag". All tags have attributes. Input configuration is:
...
<tags attribute1="value1" attribute2="value2">
<innerTag attribute3="value3"/>
<innerTag attribute4="value4"/>
</tags>
...
My task is implementation of attribute1 and attribute2 for innerTags after unmarshaling. It must be unmarshal like such xml:
...
<tags>
<innerTag attribute1="value1" attribute2="value2" attribute3="value3"/>
<innerTag attribute1="value1" attribute2="value2" attribute4="value4"/>
</tags>
...
I create the classes that will represent the objects after parsing XML:
#XmlRootElement
class Tags {
private ArrayList<InnerTag> innerTags = new ArrayList<>();
private String attribute1;
private String attribute2;
...
#XmlElement(name = "innerTag")
#XmlElementWrapper(name="tags")
public ArrayList<InnerTag> getInnerTags(){
return innerTags;
}
...
#XmlAttribute
public String getAttribute1(){
return attribute1;
}
#XmlAttribute
public String getAttribute2(){
return attribute2;
}
...
}
And the InnerTag class:
#XmlRootElement
class InnerTag {
private String attribute1;
private String attribute2;
private String attribute3;
private String attribute4;
...
#XmlAttribute
public String getAttribute1(){
return attribute1;
}
#XmlAttribute
public String getAttribute2(){
return attribute2;
}
...
#XmlAttribute
public String getAttribute3(){
return attribute3;
}
#XmlAttribute
public String getAttribute4(){
return attribute4;
}
}
I have no idea how to implement the attributes and values of parent attribute for children... I have not found such JAXB derective that let me do such implementation of attributes. Help, please to solve this problem!
try with this,
unmarshal the Tags object firstly
File file = new File("XMLFile.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Tags.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Tags tags = (Tags) jaxbUnmarshaller.unmarshal(file);
then, attribute's (attribute1 and attribute2) values of tags set to the InnerTag
for (int i = 0; i < tags.getInnerTags().size(); i++) {
tags.getInnerTags().get(i).setAttribute1(tags.getAttribute1());
tags.getInnerTags().get(i).setAttribute2(tags.getAttribute2());
}
I have the following JAXB entity:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = EntityConstants.PARTNER)
public class FilePartner
{
#XmlAttribute(name = EntityConstants.IDENTIFIER, required = true)
private String identifier;
#XmlElement(name = EntityConstants.NAME)
private String name;
#XmlElement(name = EntityConstants.ROOT_PATH)
private String rootPath;
...
}
which serialized into a similar structure:
<file-partner identifier="foo">
<name>bar</name>
<root-path>path123</root-path>
...
</file-partner>
I also have an entity which represents a list of partners:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = EntityConstants.PARTNERS)
public class FilePartnerList
{
#XmlElement(name = EntityConstants.PARTNER)
private List<FilePartner> partners = new ArrayList<FilePartner>();
public List<FilePartner> getPartners()
{
return partners;
}
public void addPartners(List<FilePartner> partners)
{
this.partners.addAll(partners);
}
}
which serializes into:
<partners>
<file-partner identifier="foo">
...
</file-partner>
<file-partner identifier="foo2">
...
</file-partner>
...
</partners>
I am looking for a way to force the jaxb unmarshaller to deserialize XMLs in the form of
<file-partner identifier="foo">
<name>bar</name>
<root-path>path123</root-path>
...
</file-partner>
into FilePartnerList instances with list size of 1, i.e:
JAXBContext context = JAXBContext.newInstance(FilePartner.class, FilePartnerList.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
InputStream inputStream = getResourceAsStream(filePartnerAsXml);
FilePartnerList partnerList = (FilePartnerList) unmarshaller.unmarshal(inputStream); // This SHOULD be unmarshalled to FilePartnerList instead of FilePartner
assertTrue(partnerList.getPartners().getSize().equals(1));
How do I achieve that?
private List<FilePartner> partners = new ArrayList<FilePartner>(**1**);
That way you'll get a fixed size input array....
But I'm sure that you will want to get the XSD of that model with the 'maxocurrs=1' so you will end modifying the XSD manually.
Anyway: why don't you, if the list size must be fixed to '1', simply set it as a simple node with a single child? Something like this (untested):
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = EntityConstants.PARTNERS)
public class FilePartnerList
{
#XmlElement(name = EntityConstants.PARTNER)
private FilePartner partners;
public FilePartner getFilePartner()
{
return partner;
}
public void setPartner(FilePartner partner)
{
this.partner = partner;
}
}
This way you will have one and only one partner per parnets-list.
The XML that fullfits the XSD of your service a text and in that text is indistinguible a list with max size 1 and a node.
I know to create a JAXB Class to marshal/unmarshall an xml like this
<outertag>
<innerelement>
<innerElementDetail1>some value</inner-element-detail1>
</innerelement>
</outertag>
here is the class I created
#XmlRootElement(name ="outertag")
#XmlAccessorType(XmlAccessType.FIELD)
public class OuterTag {
#XmlElement(name = "innerelement")
private List<InnerElement> innerElemements
public static InnerElement{
private String innerElementDetail;
// getters and setters
}
}
If I have to have an attribute on one of the inner elements like this
<outertag>
<innerelement attribute1="attribute1value">
<innerElementDetail1>some value</inner-element-detail1>
</innerelement>
</outertag>
how do I do that ?
This should do it :
#XmlRootElement(name ="outertag")
#XmlAccessorType(XmlAccessType.FIELD)
public class OuterTag {
#XmlElement(name = "innerelement")
private List<InnerElement> innerElemements
public static InnerElement{
#XmlAttribute(name = "attribute1")
protected String attribute1;
private String innerElementDetail;
// getters and setters
}
}
I wants to make xml from javabean like below:
<tag2>message</tag2>
<tag3>message</tag3>
<tag4 id='UNIQUE MT ID 1'>MOBILE No.</tag4>
I tried below code in javabean:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "name", propOrder = {"tag2", "tag3", "tag4"})
public class newBean {
#XmlElement(required = true)
private List<String> tag2;
#XmlElement(required = true)
private List<String> tag3;
#XmlElement(required = true)
private List<String> tag4;
#XmlPath("tag4/#id")
private List<String> id;
public List<String> getTag2() {
return tag2;
}
public void setTag2(List<String> tag2) {
this.tag2 = tag2;
}
public List<String> gettag4() {
return tag4;
}
public void settag4(List<String> tag4) {
this.tag4 = tag4;
}
public List<String> getId() {
return id;
}
public void setId(List<String> identifier) {
this.id = identifier;
}
public List<String> gettag3() {
return tag3;
}
public void settag3(List<String> tag3) {
this.tag3 = tag3;
}
}
I am getting below error:
Errorcom.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Property id is present but not specified in #XmlType.propOrder
this problem is related to the following location:
at private java.util.List model.newBean.id
at model.newBean
Please help me.I am using #XmlPath tag and generating error.I searched alot and found that #XmlPath usage is same as above i used but still getting error.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
About #XmlPath
#XmlPath is a EclipseLink JAXB (MOXy) extension and requires that you are using MOXy as your JAXB provider:
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
Valid Use Case #1
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "name", propOrder = { "tag4", "id" })
public class newBean {
#XmlElement(required=true)
String tag4;
#XmlPath("tag4/#id")
String id;
}
Valid Use Case #2
import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "name", propOrder = { "tag4", "id" })
public class newBean {
#XmlPath("tag4/#id")
List<String> id;
}
Invalid Use Case
import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "name", propOrder = { "tag4", "id" })
public class newBean {
#XmlElement(required=true)
List<String> tag4;
#XmlPath("tag4/#id")
List<String> id;
}
Mapping Your Use Case
You could introduce an object that corresponds to the tag4 element that has two properties corresponding to the id attribute and text. This would work with any JAXB (JSR-222) implementation.
newBean
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "name", propOrder = { "tag4", "id" })
public class newBean {
List<Tag4> tag4;
}
Tag4
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class Tag4 {
#XmlAttribute
private String id;
#XmlValue
private String value;
}
For More Information
http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html
#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