Adding attribute to xml element within JAXB API - java

I am using JAXB API for mapping a Java object to XML. My Java class is
#XmlRootElement(name = "ad")
#XmlAccessorType(XmlAccessType.FIELD)
class Item {
#XmlElement(name = "id", nillable = false)
#XmlCDATA
private int id;
#XmlElement(name = "url", nillable = false)
#XmlCDATA
private String url;
public Item() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
Output is like this :
<ad>
<id><![CDATA[ 104 ]]></id>
<url><![CDATA[www.google.com]]></url>
</ad>
I need to add an attribute to url element, for example :
<ad>
<id><![CDATA[ 104 ]]></id>
<url type="fr"><![CDATA[www.google.fr]]></url>
</ad>
I have tried many combinaisons using #XmlValue and #XmlAttribute ...

Your url variable should not be a String, but should be its own type. You should create a separate class for the url item, Url, and give it a String field, type, with an #XmlAttribute annotation.
For example,
#XmlRootElement(name = "ad")
#XmlAccessorType(XmlAccessType.FIELD)
class Item {
#XmlElement(name = "id")
private int id;
#XmlElement(name = "url")
private Url url;
public Item() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
// #XmlAttribute
public Url getUrl() {
return url;
}
public void setUrl(Url url) {
this.url = url;
}
}
#XmlRootElement(name = "url")
#XmlAccessorType(XmlAccessType.FIELD)
class Url {
#XmlValue
private String value;
#XmlAttribute(name = "type")
private String type;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Note that I don't have MOXY so I can't use or test your #XmlCDATA annotation.

Related

How to parse XML tag by Javax.xml library

I'm trying to parse a simple XML file, like this:
<customer id="100">
<age value=" 29"/>
<name value="Bob"/>
</customer>
I used the library of JAX in this way:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
#XmlAttribute(name = "id")
String id;
#XmlAttribute(name = "value")
String value;
String name;
String age;
public String getName() {
return name;
}
#XmlElement(name = "value")
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
#XmlElement(name = "value")
public void setAge(String age) {
this.age = age;
}
public String getId() {
return id;
}
#XmlElement(name = "id")
public void setId(String id) {
this.id = id;
}
}
There is an IllegalAnnotationExceptions.
I was expired by this link: here but without success.
Since "name" and "age" values are in fact attributes of child nodes, you should extract it into separate class, kinda:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public static class Customer {
#XmlAttribute
String id;
#XmlElement
NameAgeValue name;
#XmlElement
NameAgeValue age;
public String getId() {
return id;
}
public String getAge() {
return (age == null) ? null : age.value;
}
public String getName() {
return (name == null) ? null : name.value;
}
}
#XmlType
public static class NameAgeValue {
#XmlAttribute
String value;
}

In Spring mvc How to add add set values to mysql

My goal :
In Spring MVC I have to save mobile phone contact list into database.
example:
phone1 sonia 2554654 work
2554654 home
multiple phone_number with multiple phone_Number type
contacts table
id,
contact_name
phone_number
phone_type
in my java class I have
public class ContactMobile {
private String type;
private String number;
public ContactMobile() {
}
public ContactMobile(String type, String number) {
super();
this.type = type;
this.number = number;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
and here I use SET for phone number and type
#Entity
#Table(name = "_contact")
public class MobileContact {
private String id;
private String fullname;
private Set<ContactMobile> mobileNumbers;
public MobileContact(String fullname, Set<ContactMobile> mobileNumbers) {
super();
this.fullname = fullname;
this.mobileNumbers = mobileNumbers;
}
#Id
#Column(name = "Id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name = "fullname")
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public Set<ContactMobile> getMobileNumbers() {
return mobileNumbers;
}
public void setMobileNumbers(Set<ContactMobile> mobileNumbers) {
this.mobileNumbers = mobileNumbers;
}
public MobileContact() {
super();
}
}
I am using hibernate to store data..
my question is in my MobileContact class in
public Set<ContactMobile> getMobileNumbers() {
return mobileNumbers;
}
what annotation I have to use here to save multiple phonenumbers?
The MobileContact entity has many ContactMobile, it is a OneToMany relation. In your ContactMobile table, you should has a field for the id of MobileContact, like mobile_contact_id, and set the join column on that field as below in your ContactMobile:
#OneToMany(fetch = FetchType.LEZY)
#JoinColumn(name = "mobile_contact_id")
private Set<ContactMobile> mobileNumbers;
You can get the detail about the relation in this.
You can use the Embeddables (instead of Entities) for very simple value objects like MobileContact (then they do not need an ID, and the are no just simple value objects without own identity)
#Embeddable
public class ContactMobile {...
//implement an equals and hashcode method!
}
public class MobileContact {
...
#ElementCollection
private Set<ContactMobile> mobileNumbers;
...
}
#See Java Persistence/ElementCollection

JAXB Moxy Element inside Text Content

I have to un-/marshall the following snippet
<para sizeInfoId="sizeInfo2" styleId="mono">Franz jagt im komplett verwahrlosten <protectedText>Taxi</protectedText> quer durch Bayern.</para>
My Java Model looks like this
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
#XmlType(propOrder = { AcrossParagraph.XML_ID, AcrossParagraph.XML_STYLE_ID, AcrossParagraph.XML_SIZEINFO_ID, AcrossParagraph.XML_COMMENT, AcrossParagraph.XML_CONTENT })
#XmlRootElement(name = AcrossParagraph.XML_ROOT_TAG)
public class AcrossParagraph {
public static final String XML_ROOT_TAG = "para";
public static final String XML_ID = "id";
public static final String XML_STYLE_ID = "styleId";
public static final String XML_SIZEINFO_ID = "sizeInfoId";
public static final String XML_COMMENT = "comment";
public static final String XML_CONTENT = "content";
private String id;
private String styleId;
private String sizeInfoId;
private String comment;
private String content;
#XmlAttribute(name = AcrossParagraph.XML_ID)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlAttribute(name = AcrossParagraph.XML_STYLE_ID)
public String getStyleId() {
return styleId;
}
public void setStyleId(String styleId) {
this.styleId = styleId;
}
#XmlTransient
public void setStyleId(AcrossStyle style) {
this.styleId = style.getId();
}
#XmlAttribute(name = AcrossParagraph.XML_SIZEINFO_ID)
public String getSizeInfoId() {
return sizeInfoId;
}
public void setSizeInfoId(String sizeInfoId) {
this.sizeInfoId = sizeInfoId;
}
#XmlTransient
public void setSizeInfoId(AcrossSize size) {
this.sizeInfoId = size.getId();
}
#XmlAttribute(name = AcrossParagraph.XML_COMMENT)
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
#XmlValue
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
Without the inner protectedText Tag everything is working, but I don't know how to map that inner element.
I have read something about XmlAnyElement Annotation but havn't found an example for mapping something like this.
Any ideas?
Best regards,
Pascal
create new class for protectedText element:
#XmlRootElement(name = "protectedText")
class ProtectedText implements Serializable{
#XmlValue
public String value;
}
now change content property in AcrossParagraph as below:
private List<Serializable> content;
#XmlElementRef(name = "protectedText", type = ProtectedText.class)
#XmlMixed
public List<Serializable> getContent(){
return content;
}
public void setContent(List<Serializable> content){
this.content = content;
}
when you unmarshal the content list contains mix of String and ProtectedText

map 2 collection types using modelmapper

I am developing and spring application and for object mapping I am using ModelMapper library.
I am able to map basic class mapping but when I am trying to map 2 collection elements, source is set of enumeration with additional property like name and description and destination is pojo having id, name and description.
I have tried typemap and converters in mapping profile but I am getting exception of mapper.
And the source class is from other application(whose dependency have been added in pom.xml). I also don't want source type as an argument in setter of destination.
Ex.
SOURCE:
public class VType{
private int id;
private String name;
private String description;
}
public class VDTO{
private Set<VType> vTypes;
public Set<VType> getVTypes(){
return this.vTypes;
}
public void setVType() { //here I don't want to pass source type as an argument
//code stuff that I don't know what to do here
}
}
SOURCE ENUM:
public enum SourceVType{
V1(1, "Name1", "Desc1");
V2(2, "Name2", "Desc2");
private Integer id;
private String name;
private String description;
SourceVType(Integer id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
}
//getter-setter
}
Have you tried converter feature of modelmapper. You can use typemap converter to achieve this requirement.
#RunWith(JUnit4.class)
public class TempTest {
#Test
public void TestThis(){
final ModelMapper mapper = new ModelMapper();
mapper.addMappings(new PropertyMap<SrcClass, DestClass>() {
#Override
protected void configure() {
this.map().setId(this.source.getId());
this.map().setName(this.source.getName());
mapper.createTypeMap(TypeEnum.class, TypeClass.class).setConverter(
new Converter<TypeEnum, TypeClass>() {
#Override
public TypeClass convert(MappingContext<TypeEnum, TypeClass> mappingContext) {
if (mappingContext.getSource() == null) {
return null;
}
TypeEnum typeEnum = mappingContext.getSource();
TypeClass typeClass = new TypeClass();
typeClass.setId(typeEnum.getId());
typeClass.setName(typeEnum.getName());
return typeClass;
}
});
}
});
SrcClass srcObj = new SrcClass();
srcObj.setId(1);
srcObj.setName("name");
srcObj.setTypes(new HashSet<>(Arrays.asList(TypeEnum.TYPE1, TypeEnum.TYPE2)));
DestClass dstObj = mapper.map(srcObj, DestClass.class);
Assert.assertEquals(srcObj.getId(), dstObj.getId());
Assert.assertEquals(srcObj.getName(), dstObj.getName());
Assert.assertEquals(srcObj.getTypes().size(), dstObj.getTypes().size());
for(TypeClass c : dstObj.getTypes()) {
TypeEnum e = TypeEnum.getById(c.getId());
Assert.assertNotNull(e);
Assert.assertTrue(srcObj.getTypes().contains(e));
}
}
public static <Source, Result> Set<Result> convertAll(Set<Source> source, Function<Source, Result> projection)
{
Set<Result> results = new HashSet<>();
if(source == null) return results;
for (Source element : source)
{
results.add(projection.apply(element));
}
return results;
}
public static class SrcClass{
private Integer id;
private String name;
private Set<TypeEnum> types;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<TypeEnum> getTypes() {
return types;
}
public void setTypes(Set<TypeEnum> types) {
this.types = types;
}
}
public static class DestClass{
private Integer id;
private String name;
private Set<TypeClass> types;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<TypeClass> getTypes() {
return types;
}
public void setTypes(Set<TypeClass> types) {
this.types = types;
}
}
public static enum TypeEnum{
TYPE1(1, "Type 1")
, TYPE2(2, "Type 2")
, TYPE3(3, "Type 3")
, TYPE4(4, "Type 4");
private Integer id;
private String name;
TypeEnum(Integer id, String name) {
this.id = id;
this.name = name;
}
private static final Map<Integer, TypeEnum> byId = new HashMap<>();
private static final Map<String, TypeEnum> byName = new HashMap<>();
static {
for (TypeEnum e : TypeEnum.values()) {
if (byId.put(e.getId(), e) != null) {
throw new IllegalArgumentException("duplicate id: " + e.getId());
}
if (byName.put(e.getName(), e) != null) {
throw new IllegalArgumentException("duplicate name: " + e.getName());
}
}
}
public Integer getId() {
return this.id;
}
public String getName() { return this.name; }
public static TypeEnum getById(Integer id) {
return byId.get(id);
}
public static TypeEnum getByName(String name) {
return byName.get(name);
}
}
public static class TypeClass{
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

Parsing XML data into string objects using JAXB

I have to parse a xml into string objects in JAXB. But how to creates objects for this xml
Country.xml
<?xml version="1.0" encoding="UTF-8"?>
<Country>
<name>India</name>
<capital>New Delhi</capital>
<population>120crores</population>
.
.
.
.
.
<states>
<state>
<name>Maharastra</name>
<pincode>xyzzzz</pincode>
<capital>Mumbai</capital>
<\state>
<state>
.
.
.
</state>
</states>
<\Country>
And to parse this xml I have created class to map the objects which creates the objects and print it in the console. But Don't know what I am doing wrong.
#XmlElementWrapper(name="Country")
public void setCountry(String Countryv) {
Country= Countryv;
}
#XmlElement (name = "name")
public void setname(String namev) {
name= namev;
}
#XmlElement (name = "capital")
public void setcapital(String capitalv) {
capital= capitalv;
}
#XmlElement (name = "population")
public void setpopulation(String populationv) {
population= populationv;
}
#XmlElementWrapper(name="states")
public void setType(String statesv) {
states = statesv;
}
#XmlElementWrapper(name="state")
public void setType(String statev) {
state = statev;
}
#XmlElement (name = "name")
public void setpopulation(String namev) {
name= namev;
}
#XmlElement (name = "pincode")
public void setpopulation(String pincodev) {
pincode= pincodev;
}
#XmlElement (name = "capital")
public void setpopulation(String capitalv) {
capital= capitalv;
}
when I run the program I m getting the
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException:
counts of IllegalAnnotationExceptions
How to add wrapper anotations to wrapping the elements under separate headers and headers inside other headers.
Try this class
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"name",
"capital",
"population",
"states"
})
#XmlRootElement(name = "Country")
public class Country {
#XmlElement(required = true)
protected String name;
#XmlElement(required = true)
protected String capital;
#XmlElement(required = true)
protected String population;
#XmlElement(required = true)
protected Country.States states;
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public String getCapital() {
return capital;
}
public void setCapital(String value) {
this.capital = value;
}
public String getPopulation() {
return population;
}
public void setPopulation(String value) {
this.population = value;
}
public Country.States getStates() {
return states;
}
public void setStates(Country.States value) {
this.states = value;
}
This worked for me
class Country {
#XmlElement
String name;
//...
#XmlElementWrapper(name="states")
List<State> state;
}
class State {
#XmlElement
String name;
//..
}

Categories