I have question about how to add additional attributes to a root tag of an xml-structure.
let say this is my java-class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "myRoot")
#XmlType(name = "myType")
public class A implements B {
#CoId
private int id;
public int getId() {
return id;
}
}
and I want as result an output which can be like this below:
"<myRoot newAttribute="something">
<id>111</id>
</myRoot>"
I mean the attribute newAttribute should be dynamically added. What is the annotation for this, how should I adapt my class here?
Related
I would like to unmarshall an object using JAXB based on the enum value/string present in the xml. I have several classes inheriting from one abstract class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlSeeAlso({ InheritingClassOne.class, InheritingClassTwo.class })
public abstract class BasicClass {
protected String type; //determines class type
protected String description;
//getters & setters
}
two examplary subclasses:
#XmlRootElement(name = "someRoot")
#XmlAccessorType(XmlAccessType.FIELD)
public class InheritingClassOne extends BasicClass {
private String message;
private Float mark;
//getters & setters
}
#XmlRootElement(name = "someRoot")
#XmlAccessorType(XmlAccessType.FIELD)
public class InheritingClassTwo extends BasicClass {
private Integer value;
//getters & setters
}
I know that JAXB can unmarshall objects based on xsi:type attribute, which I cannot use, since the input xml is stripped from all atributes. I have tried using Moxy #XmlDiscriminatorNode & #XmlDiscriminatorValue, but these seem to work only with attributes and not the element values.
I have also seen #XmlElementRef which lets determine the type based on the name of the element, but again, due to some restrictions all elements have to have the same name in input and output xml.
My input xml is:
<someRoot>
<type>chooseOne</type>
<message>Message for InheritingClassOne</message>
<mark>12.3</mark>
</someRoot>
I did not find solution for this problem other than using #XmlJavaAdapter with defined adapter:
public class CustomAdapter extends XmlAdapter<Object, BasicClass> {
#Override
public BasicClass unmarshal(Object v) throws Exception {
//TODO: cast v to Element interface, get to type element value and handle accordingly
return null;
}
#Override
public Object marshal(BasicClass v) throws Exception {
//TODO: marshal
return null;
}
}
The adapter solution with reading ElementNsImpl child values to get the category seems awful and takes a lot of effort for such task. Are there any solutions that I am missing? Can I somehow change my models (without using xml attributes), so this task is doable?
I've been trying to search how to do this but I haven't found an answer to my exact requirements:
Let's say we had this 3 classes:
public class Main {
public ArrayList<MyFirstClass> myFirstClass;
}
class MyFirstClass {
public int num;
public MySecondClass mySecondClass;
}
class MySecondClass {
public String otherStr;
public MyThirdClass myThirdClass;
}
class MyThirdClass {
public int otherNum;
}
I wanto to be able to read these XML with the unmarshaller:
<Main>
<MyFirstClasses>
<MyFirstClass>
<num>1</num>
<MySecondClass>
<str>Hello</str>
<MyThirdClass>
<otherNum>2</otherNum>
</MyThirdClass>
</MySecondClass>
</MyFirstClass>
<MyFirstClasses>
</Main>
Where I'm basically able to set the variables that are objects (MySecond/Third Class).
I know I can use #XMLRootElement and then #XmlElementWrapper(name="aName") and #XmlElement(name="aName") to do the
<Main>
<MyFirstClasses>
<MyFirstClass>
<num>1</num>
</MyFirstClass>
<MyFirstClasses>
</Main>
But how can I then nest the MySecondClass inside MyFirstClass so I can set it's values, because otherwise the FirstClassObject will have a MySecondClass which has null values.
Thanks in advance!
The problem is that your xml does not match your POJOs. You can use annotations to fix this(renaming fields would also work). Try this:
#XmlRootElement(name = "Main")
public class Main {
#XmlElementWrapper(name = "MyFirstClasses")
#XmlElement(name = "MyFirstClass")
private List<MyFirstClass> myFirstClass;
}
Then FirstClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MyFirstClass {
private int num;
#XmlElement(name = "MySecondClass")
private MySecondClass mySecondClass;
}
And MySecondClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MySecondClass {
private String str;
#XmlElement(name = "MyThirdClass")
private MyThirdClass myThirdClass;
}
Finally MyThirdClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MyThirdClass {
public int otherNum;
}
I'm currently trying to change lots of XML into Java objects but I keep getting stuck. I have tried copying lots of different examples online but I can never seem to get the right way and I find it very hard to debug.
My XML looks like this
<?xml version="1.0" encoding="utf-8"?>
<XMLSOCCER.COM>
<TeamLeagueStanding xmlns="http://xmlsoccer.com/LeagueStanding">
<Team>Leicester</Team>
<Team_Id>31</Team_Id>
<Played>26</Played>
<PlayedAtHome>12</PlayedAtHome>
<PlayedAway>14</PlayedAway>
<Won>15</Won>
<Draw>8</Draw>
<Lost>3</Lost>
<NumberOfShots>464</NumberOfShots>
<YellowCards>40</YellowCards>
<RedCards>1</RedCards>
<Goals_For>48</Goals_For>
<Goals_Against>29</Goals_Against>
<Goal_Difference>19</Goal_Difference>
<Points>53</Points>
</TeamLeagueStanding>
<TeamLeagueStanding xmlns="http://xmlsoccer.com/LeagueStanding">
<Team>Tottenham</Team>
<Team_Id>21</Team_Id>
...
So I just have a list of TeamLeagueStanding s that I want to keep as Team objects. My java code for the Team class is currently like this
#XmlRootElement(name = "TeamLeagueStanding")
public class Team {
#XmlElement(name = "Team")
String teamName;
#XmlElement(name = "Team_Id")
int teamID;
public Team (String team, int id) {
super();
this.teamName = team;
this.teamID = id;
}
}
My Teams class which is just to hold the list of Teams is like this
#XmlRootElement(name = "XMLSOCCER.COM")
public class Teams {
#XmlElement
List<Team> teamList;
public Teams () {
}
}
and my main function is like this
public class Main {
public static void main(String[] args) throws Exception {
File xml = new File("data/GetLeagueStandingsPrem1516.xml");
JAXBContext jc = JAXBContext.newInstance(Teams.class);
Unmarshaller um = jc.createUnmarshaller();
Teams t = (Teams) um.unmarshal(xml);
System.out.println(t.teamList.size());
}
}
I've tried this so many ways and I always get either a null pointer exception or various IllegalAnnotationExceptions. If anyone has any idea where I'm going wrong I would greatly appreciate any pointers!
Thanks,
Simon
I think you should add #XmlAccessorType(XmlAccessType.FIELD) annotation
#XmlRootElement(name = "TeamLeagueStanding")
#XmlAccessorType(XmlAccessType.FIELD)
public class Team {
}
Your root element seems to be XMLSOCCER.COM
1. create xsd
2. using xjc command create java bean classes or you can use IDE to create objects.
3.keep created xml bean objects under src
4. then you pass the xml to be unmarshelled
5. you will get converted objects hierarchically you can access.
Add default constructor to Team class
Add
#XmlElement(name = "TeamLeagueStanding")
List<Team> teamList;
to Teams class;
Team.class:
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "TeamLeagueStanding")
public class Team {
#XmlElement(name = "Team")
String teamName;
#XmlElement(name = "Team_Id")
int teamID;
public Team (){
}
public Team (String team, int id) {
super();
this.teamName = team;
this.teamID = id;
}
}
Teams.class
import javax.xml.bind.annotation.*;
import java.util.List;
#XmlRootElement(name = "XMLSOCCER.COM")
#XmlAccessorType(XmlAccessType.FIELD)
public class Teams {
#XmlElement(name = "TeamLeagueStanding")
List<Team> teamList;
public Teams () {
}
}
I am working with REST services and i want to pass an XML-text with a POST request. My server is implemented in JAVA. Let's say that i am sending this XML:
<range>
<higher value="3"></higher>
<lower value="2"></lower>
</range>
As i understand (correct me if i am wrong), the easiest way to convert the XML in the request to a java object, is to define a class with the proper annotations. For example:
#XmlRootElement(name = "range")
public class RangeClass {
#XmlElement (name = "lower")
private int lower;
#XmlElement (name = "higher")
private int higher;
.
.
???
}
And then read it like this:
#POST
#PATH(<somePath>)
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.TEXT_PLAIN)
public String myFun(RangeClass range) {
.
.
.
}
The thing that i am missing (if the other parts are correct) is how to define that i have attributes inside the elements. If i put an '#XmlAttribute' annotation this will refer to an attribute of the root element ('range') and not an attribute of a specific element ('lower' or 'higher').
First and the easiest way is to create a Java mapping per each XML tag:
#XmlRootElement(name = "range")
public class RangeClass {
private Higher higher;
private Lower lower;
}
#XmlElement(name = "higher")
public class Higher {
#XmlAttribute
private int value;
}
#XmlElement(name = "lower")
public class Lower {
#XmlAttribute
private int value;
}
Second option is to change XML structure to:
<range>
<higher>3</higher>
<lower>2</lower>
</range>
Then you can use #XmlElement annotation:
#XmlRootElement(name = "range")
#XmlAccessorType(XmlAccessType.FIELD)
public class RangeClass {
#XmlElement
private int lower;
#XmlElement
private int higher;
}
Third option is to use Eclipse Link Moxy and its #XmlPath annotation:
#XmlRootElement(name = "range")
#XmlAccessorType(XmlAccessType.FIELD)
public class RangeClass {
#XmlPath("lower/#value")
private int lower;
#XmlPath("higher/#value")
private int higher;
}
Here's my intended XML structure
<Outer type="good" id="1">
<Uid>123</Uid>
<Name>Myself</Name>
<Inner type="bad">This Value</Inner>
</Outer>
Here's my Object.
#XmlAccessorType(XMLAccessType.FIELD)
#XmlType(name="Outer", propOrder = {
"uid"
"name"
"inner"
})
public class Outer{
#XmlElement(name = "Uid")
protected String uid;
#XmlElement(name = "Name")
protected String name;
#XmlElement(name = "Inner")
protected Inner inner;
public static class Inner{
#XmlAttribute
private String type;
#XmlValue
private String value;
//setters & getters for both
}
//setters & getters for all the elements
}
Now in my class I am doing
Outer o = new Outer();
o.setUid/ID/Type/Name() ; //all the setter
Inner i - new Inner();
i.setValue("This Value");
i.setType("bad");
When Irun this i am getting
If a class has #XmlElement property, it cannot have #XmlValue property.
And
Class has two properties of the same name "type" (This one is for the Source class)
And
Class has two properties of the same name "value" (This one is for Source class too)
What is happening, and what I can I do rectify this?
Thanks
Currently, JAXB threats both fields (due to annotations) and both pairs of get/set (due to default accessor type) as properties. So you class Inner has 4 properties.
Please, add own accessor type for Inner class
#XmlAccessorType(XmlAccessType.FIELD)
public static class Inner
{
Or annotate properties instead of fields
public static class Inner
{
private String type;
private String value;
#XmlAttribute
public String getType()
{
return type;
}
// setter setType
#XmlValue
public String getValue()
{
return value;
}
// setter setValue
}
Add XmlRootElement annotation to the Outer class, besides of that it shoud work.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Outer", propOrder = {"uid", "name", "inner"})
public static class Outer {