I'm not getting my "announcements" when I try to parse messages like these:
<?xml version="1.0" encoding="UTF-8"?>
<message messageType="SUBSCRIBER" messageName="ANNOUNCEMENT">
<announcement time="12:30">
Lunchtime!
</announcement>
<announcement time="32:00">
Good night ...
</announcement>
<errorText>Phone number missing, subscriber: Dick</errorText>
</message>
The JAXB Java class seemed pretty straightforward. And is based on similar messages that work. In this case the difference seems to be that I can have two different types of nested element (XmlElement) in the main block.
The code below actually parses the XML but it doesn't call the Announcement.setMessageText() method. Whereas I can see that the time attribute is set from the XML and I have an array size=2 for announcements, it reads and sets the single errorText XmlElement. Btw, I also removed the tag from the code and XML -- Not change in treatment of my messageText. Ideas welcome!
#XmlRootElement(name = "message")
public class AnnouncementMessage
{
#XmlAttribute
public String getMessageName(){
return this.messageName;
}
public void setMessageName( String name ){
this.messageName = name;
}
#XmlAttribute
public String getMessageType(){
return messageType;
}
public void setMessageType( String newMessageType ){
this.messageType = newMessageType;
}
#XmlElement(name = "errorText")
public String getErrorText(){
return errorText;
}
public void setErrorText( String newMsg ){
this.errorText = newMsg;
}
private List<Announcement> announcements = new ArrayList<>();
#XmlElement(name = "announcement")
public List<Announcement> getAnnouncements(){
return this.announcements;
}
public void setAnnouncements( List<Announcement> newAnnouncements ){
this.announcements = newAnnouncements;
}
}
And the Announcement class:
#XmlRootElement(name = "announcement")
public class Announcement
{
private String messageText = "";
private String time = "12:00";
XmlAttribute(name ="time")
public String getTime(){
return this.time;
}
public void setTime( String newMsg ){
this.messageText = time;
}
#XmlElement(name="announcement")
public String getMessageText(){
return this.messageText;
}
public void setMessageText( String newMsg ){
this.messageText = newMsg;
}
Announcement(){
}
}
Using the name parameter in the for the XmlElement seem to make no difference. My thanks in advance.
Use the #XmlValue annotation for the message text:
#XmlValue
public String getMessageText(){
return this.messageText;
}
Additionally, as noted in this related answer by OP, an #XmlAccessorType(XmlAccessType.NONE) is needed on the Announcement class if it contains getter/setter pairs that are not mapped to/from XML and don't have an #XmlTransient annotation.
Related
I have a XML response from REST API like below :
<?xml version="1.0" encoding="UTF-8"?>
<ns2:testpla xmlns:ns2="http:xyz" xmlns:ns7="xyz">
<ns2:category term="Default Category" value="Default Category Value"/>
<ns2:testase ns7:resource="https://www.cyz.com" units="PH"
href="ww.com">XYZ</ns2:testase>
<ns2:testase ns7:resource="https://ww.cyz.com" units="LH"
href="ww.org">AZ</ns2:testase>
<com.abc xmlns="http://lq.net" extensionDisplayName="QWZ-KEY-TP-TEST-ZWE-
TI">
<div xmlns="http://www.w3.org/1999/xhtml">TriggerA ND confirm the
functionality</div>
</com.abc>
</ns2:testpla>
I know how to get the xml element value ie"XYZ"using jaxb and bind to bean. But I'm stuck on know how to fetch the value of resource(ie;"https://www.cyz.com"),units("PH"),href("ww.com"),value of xmlns inside div ?And then to map the value to object property.
Please help me.
create the separate two classes for testpla and testase
Testpla.java
#XmlRootElement(name = "ns2:testpla")
public class Testpla {
private Testase testase;
public Testase getTestase() {
return testase;
}
#XmlElement(name = "ns2:testase")
public void setTestase(Testase testase) {
this.testase = testase;
}
}
Testase.java
#XmlRootElement(name = "ns2:testase")
public class Testase {
private String resource;
private String units;
public String getResource() {
return resource;
}
#XmlAttribute(name = "ns7:resource")
public void setResource(String resource) {
this.resource = resource;
}
public String getUnits() {
return units;
}
#XmlAttribute(name = "units")
public void setUnits(String units) {
this.units = units;
}
}
I'm trying to unmarshal existing xml file so that i can handle the data properly but the XML structure looks weird. below is the sample of the xml together with the objects I've created.
<?xml version="1.0" encoding="UTF-8"?>
<Record>
<identifier>11</identifier>
<TotalRecords>266</TotalRecords>
<ListOfSections>
<SECTION>AA1001</SECTION>
<ListOfStudents>
<SequenceNumber>11</SequenceNumber>
<RecordCount>1</RecordCount>
<StudentId>201614354</StudentId>
</ListOfStudents>
<SECTION>AA1002</SECTION>
<ListOfStudents>
<SequenceNumber>15</SequenceNumber>
<RecordCount>1</RecordCount>
<StudentId>201614356</StudentId>
<SequenceNumber>16</SequenceNumber>
<RecordCount>2</RecordCount>
<StudentId>201614355</StudentId>
</ListOfStudents>
</ListOfSections>
</Record>
Below are my java classes. I just removed the variables for readability.
#XmlRootElement
public class Record {
#XmlElement(name = "TotalRecords")
public Integer getTotalNoOfRecords() {
return totalNoOfRecords;
}
#XmlElement(name = "ListOfSections")
public List<Section> getSectionList() {
return sectionList;
}
}
#XmlRootElement
public class Section {
#XmlElement(name = "SECTION")
public String getSection() {
return section;
}
#XmlElement(name = "ListOfStudents")
public List<Student> getStudentList() {
return studentList;
}
}
#XmlRootElement
public class Student {
#XmlElement(name = "SequenceNumber")
public Integer getSequenceNumber() {
return sequenceNumber;
}
#XmlElement(name = "RecordCount")
public Integer getRecordCount() {
return recordCount;
}
#XmlElement(name = "StudentId")
public Integer getStudentId() {
return studentId;
}
}
I was trying to get all the records within the ListOfSections tag but I'm only getting the last section which is AA1002.
for the ListOfStudents I'm only getting the first record in my case I'm only getting record with sequence number 15
<SequenceNumber>12</SequenceNumber>
<RecordCount>2</RecordCount>
<StudentId>201614355</StudentId>
This simplified code works with your xml, it should give you a hint where to look for the problem:
class Record {
#XmlElementWrapper(name="ListOfSections")
#XmlElement(name="SECTION")
List<String> listOfSections;
}
here how to run:
Record r = JAXB.unmarshal(new File("1.xml"), Record.class);
System.out.println(r.listOfSections);
result:
[AA1001, AA1002]
I'm trying to unmarshall this kind of XML:
<result>
<avance>0.0000</avance>
<operation_status>0</operation_status>
<service>Bank Account</service>
<service>
<min_amount>1.00</min_amount>
<max_amount>1499.00</max_amount>
<currency>USD</currency>
</service>
</result>
I have created this kind of class structure:
public class Result {
private BigDecimal avance;
private Integer operationStatus;
private String serviceDesc;
private Service service;
#XmlElement(name = "service")
public String getServiceDesc() {
return serviceDesc;
}
public void setServiceDesc(String serviceDesc) {
this.serviceDesc = serviceDesc;
}
#XmlElement(name = "service")
public Service getService() {
return service;
}
public void setService(Service service) {
this.service = service;
}
#XmlElement(name = "avance")
public BigDecimal getAvance() {
return avance;
}
public void setAvance(BigDecimal avance) {
this.avance = avance;
}
#XmlElement(name = "operation_status")
public Integer getOperationStatus() {
return operationStatus;
}
public void setOperationStatus(Integer operationStatus) {
this.operationStatus = operationStatus;
}
}
and Service looks like this:
#XmlRootElement
public class Service {
private BigDecimal minAmount;
private BigDecimal maxAmount;
private String currency;
#XmlElement(name = "min_amount")
public BigDecimal getMinAmount() {
return minAmount;
}
public void setMinAmount(BigDecimal minAmount) {
this.minAmount = minAmount;
}
#XmlElement(name = "max_amount")
public BigDecimal getMaxAmount() {
return maxAmount;
}
public void setMaxAmount(BigDecimal maxAmount) {
this.maxAmount = maxAmount;
}
#XmlElement(name = "currency")
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
}
When I receive response from some external service I'm able to unmarshal that string and result has correct Service class set but serviceDesc is always null. Is there any way how I can unmarshall this structure correctly?
In another question (for which this question is marked as duplicate) case is when you have same tag name but different number of attributes in my case content of the tag is different, also in that question classes to which content should be unmarshaled are child and parent in my case one is String another one some custom object. Think that's why I wasn't able to implement XmlAdapter properly.
Your XML structure is not valid.
You shouldn't have the same tag twice for different structure in the same namespace.
Solutions :
Rename your tag (serviceDesc for example)
Use 2 different namespaces ( ns1:service and ns2:service for example)
I am new to Jaxb and having problem parsing a simple XML. The XML in question is shown below:
<tables>
<table id="1" >
<schema>validator_test</schema>
<name>test1</name>
<rowCountToValidate>6</rowCountToValidate>
<columnTypeCheckRequired>FALSE</columnTypeCheckRequired>
<additionalColumns>column1,column2</additionalColumns>
</table>
<table id="2">
<schema>validator_test</schema>
<name>validate_external1</name>
<rowCountToValidate>2</rowCountToValidate>
<columnTypeCheckRequired>FALSE</columnTypeCheckRequired>
<additionalColumns>column1,column2</additionalColumns>
</table>
<table id="3">
<schema>validator_test</schema>
<name>Test_View1</name>
<rowCountToValidate>2</rowCountToValidate>
<columnTypeCheckRequired>FALSE</columnTypeCheckRequired>
<additionalColumns>column1,column2</additionalColumns>
</table>
</tables>
The Jaxb class to unmarshall this is:-
#XmlRootElement(name = "table")
#XmlType(propOrder = { "name", "schema", "rowCountToValidate","columnTypeCheckRequired","additionalColumns","targetName"})
#Service
public class TableInfo {
private static final boolean TRUE = true;
#Value("${default.row.count.to.validate}")
private Integer defaultRowCountToValidate;
/**
*
*/
public TableInfo() {
}
private String name;
private String schema;
private Integer rowCountToValidate;
private String targetName;
private String columnTypeCheckRequired;
private String additionalColumns;
#XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "schema")
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
#XmlElement(name = "rowCountToValidate")
public Integer getRowCountToValidate() {
return rowCountToValidate;
}
#XmlElement(name = "columnTypeCheckRequired")
public String getColumnTypeCheckRequired() {
return columnTypeCheckRequired;
}
public void setColumnTypeCheckRequired(String columnTypeCheckRequired) {
this.columnTypeCheckRequired = columnTypeCheckRequired;
}
#XmlElement(name = "additionalColumns")
public String getAdditionalColumns() {
return additionalColumns;
}
public void setAdditionalColumns(String additionalColumns) {
this.additionalColumns = additionalColumns;
}
public void setRowCountToValidate(Integer rowCountToValidate) {
// If user configured value is not null and greater than zero then set
// the value otherwise use default value
if ((null != rowCountToValidate) && (rowCountToValidate.intValue() > 0)) {
this.rowCountToValidate = rowCountToValidate;
}else {
this.rowCountToValidate = defaultRowCountToValidate;
}
}
#XmlElement(name = "targetName")
public String getTargetName() {
return targetName;
}
public void setTargetName(String targetName) {
this.targetName = targetName;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
However, I am ggetting the following exception:-
`JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"tables"). Expected elements are <{tables}table>`
I would really appreciate if someone can point out the error I am doing. I am new to this and am not really able to understand how jaxb works.
You need to create class Tables with #XmlRootElement(name = "tables") and that class must contain table field with type TableInfo.
When you unmarshal example xml, you need to pass Tables class to unmarshaller.
#XmlRootElement(name = "table")
<tables>
<table id="1" >
Below are the 2 solution for above issue:
You need to generate the classes using XSD.
You need to generate the classes as per your required XML:
in XML table is inside the tables so tables should be the root element.
And table should be in the form of list in tables class.
in your code root element is #XmlRootElement(name = "table") where in your XML file it is "tables"
Suggest you to use xjc command to build java POJO classes automatically
xjc -d -p sample.xsd
-d to define where the generated classes shall be stored in the file system,
-p to define the package to be used
I'm trying to deserialize an xml string with SimpleXML, i've looked at their examples but i'm not really sure that wether i grasp the concept or not.
Sample XML (validates):
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<Response xmlns="http://localhost/webservices/">
<Result>
<Item><ID>0</ID><language /><price>168</price></Item>
<Item><ID>1</ID><language /><price>178</price></Item>
<Item><ID>2</ID><language /><price>195</price></Item>
<Item><ID>3</ID><language /><price>169</price></Item>
<Item><ID>4</ID><language /><price>178</price></Item>
<Item><ID>5</ID><language /><price>178</price></Item>
<Item><ID>6</ID><language /><price>149</price></Item>
<Item><ID>7</ID><language /><price>178</price></Item>
<Item><ID>8</ID><language /><price>168</price></Item>
<Item><ID>9</ID><language /><price>179</price></Item>
<Item><ID>10</ID><language /><price>147</price></Item>
<Item><ID>11</ID><language /><price>165</price></Item>
<Item><ID>12</ID><language /><price>192</price></Item>
<Item><ID>13</ID><language /><price>218</price></Item>
<Item><ID>14</ID><language /><price>144</price></Item>
<Item><ID>15</ID><language /><price>141</price></Item>
</Result>
</Response>
</soap:Body></soap:Envelope>
And the java code:
#Root(name="Result",strict=false)
public class ItemList {
#ElementList(entry="Item")
private List<Item> _list;
public List<Book> GetItemList()
{
return _list;
}
public void SetItemList(List<Item> value)
{
this._list = value;
}
}
#Root(strict=false)
public class Item {
#Element(name="ID")
private String _ID;
#Element(name="price")
private String _price;
public String GetPrice()
{
return _price;
}
public void SetPrice(String value)
{
this._price = value;
}
public String GetID()
{
return _ID;
}
public void SetID(String value)
{
this._ID = value;
}
public Item(String ID,
String price)
{
this._ID = ID;
this._price = price;
}
}
Any help is appreciated.
I have a suggestion, but it's not ready to run (see below). However, ther maybe another, better solution ...
Class Item
Holding all your informations.
#Root(name="Item")
public class Item
{
#Element(name="ID", required=true)
private int id;
#Element(name="language", required=true)
private String language;
#Element(name="price", required=true)
private int price;
// ...
}
Class Result
Constructing everything around Item. Btw. you dont have to use inner classes here.
#Namespace(prefix="soap", reference="http://schemas.xmlsoap.org/soap/envelope/")
#Root(name="Envelope")
public class Result
{
#Namespace(prefix="soap")
#Element(name="Body")
private SoapBody body;
// ...
// -----------------------------------------------------------------
// -- Some inner classes, constructing the elements as in you xml --
// -----------------------------------------------------------------
#Namespace(prefix="soap")
#Root(name="Body")
static class SoapBody
{
#Element(name="Response")
private Response response;
// ...
}
#Root(name="Response")
static class Response
{
#ElementList(name="Result", required=true)
private List<Item> result;
// ...
}
}
(Example) How to use this code
Writing
File f = ...
Serializer ser = new Persister();
Result r = new Result();
ser.write(r, f);
Reading
File f = ...
Serializer ser = new Persister();
Result r = ser.read(Result.class, f);
Now ... there's one problem which prevents this example from running: <language />
This empty Element let SimpleXML throw a ValueRequiredException.
#Element( required=false)
private String language;
Add this in your Item class and generate the getter and setter.I think it should work