I am trying to utilize JAXB to convert xml elements gained from a youtube rss feed into objects. I seem to be following the structure of most examples I have seen, but still cannot get it to work as it always seem the list within feed is empty at all times. Does anyone know how to fix this?
Here are my classes for reference:
feed class:
import java.util.List;
import javax.xml.bind.annotation.*;
import javax.xml.*;
#XmlRootElement(
name = "feed",
namespace = "http://www.w3.org/2005/Atom"
)
#XmlAccessorType (XmlAccessType.FIELD)
public class feed {
#XmlElement(name = "entry")
private List<entry> entries;
public List<entry> getEntry() {
return this.entries;
}
public void setEntry(List<entry> entries) {
this.entries = entries;
}
}
Entry class:
import javax.xml.bind.annotation.*;
import java.util.List;
#XmlRootElement(name = "entry")
#XmlAccessorType(XmlAccessType.FIELD)
public class entry {
private String title, name, id, published;
public void settitle(String title){this.title = title;}
public String gettitle(){return title;}
public void setname(String name){this.name = name;};
public String getname() {
return name;
}
public void setid(String id){this.id = id;}
public String getid() {
return id;
}
public void setpublished(String published){this.published = published;}
public String getpublished() {return published;}
public void PrintVideoInfo(){
System.out.println(gettitle());
System.out.println(getname());
System.out.println(getid());
System.out.println(getpublished());
System.out.println("-----------");
}
}
unmarshalling class:
import java.io.File;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class XMLtoObject {
public static void main(String[] args) {
try {
File file = new File("videos.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(feed.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
feed que= (feed) jaxbUnmarshaller.unmarshal(file);
for(entry ent:que.getEntry())
ent.PrintVideoInfo();
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
https://www.youtube.com/feeds/videos.xml?channel_id=UCBcRF18a7Qf58cCRy5xuWwQ this is the xml being used. It is saved as videos.xml and the file path is correct, just not fully included for privacy in the above snippet. Any help would be greatly appreciated.
Please, make your class names follow Pascal notation - it's way easier to read and understand, especially when there's a lot of code. Probably, you should work on your code style more.
Your feed class is annotated correctly, but in order for JAXB to unmarshal XML into entries entry class should also be annotated properly. Also note, that your field names do not match tag names in the xml file provided (<name> is not directly accessible within <feed>).
So, add annotations and classes to match xml file structure.
UPDATE 1
I realized I didn't quite understand xml documents, so I made a little investigation.
If you're completely familiar with xml namespaces, then you can skip this part to Serialization section. Otherwise, read on.
Namespace is a mechanism of dividing xml nodes into non-intersecting sets. Imagine having an <address> tag in your xml, where the tag is defined many times. It could either refer to a web address or a street address, for example, and thus have completely different meaning depending on context. To avoid confusion, you add a namespace prefix like that: <web:address> <street:address> to separate them and group other elements referring to the same namespace. You define them earlier in some root tag:
<root xmlns:web="Web">
<web:address> ... </web:address>
</root>
Also, there's a special namespace - default namespace - which is defined like this: <feed xmlns="Name">. Having a default namespace allows you to omit writing namespace prefix every time you define an xml element.
Let's clear this up with your xml example: it states three namespaces for <feed> element (yt, media, and the default namespace)
<feed xmlns:yt="http://www.youtube.com/xml/schemas/2015"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns="http://www.w3.org/2005/Atom">
That means every element inside <feed> is kind of implicitly prefixed with the default namespace.
Intro to XML namespaces
Atom namespace explained
Serialization
I downloaded the xml file you provided and did some tests. It turned out, that JAXB just "didn't see" the entity tags, since they are hidden behind the default namspace, and we never said to JAXB there is a namespace at all, except for the <feed> element.
So, the solution is to annotate the elements you want to deserialize with a namespace, so that JAXB could understand that.
UPDATE 2
It looked as if the solution provided above was too messy: having to annotate every other element with a namespace is truly a violation of DRY principle. Fortunately, there is a solution to add a default namespace in just one line.
Create a file called package-info.java and add the following in it and replace package with yours:
#XmlSchema(
namespace = "http://www.w3.org/2005/Atom",
elementFormDefault = XmlNsForm.QUALIFIED
)
package package;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
All it does is defines an xml schema for the document we want to parse. You can now remove all namespace = "..." lines and pretty up the code
If you're not familiar with xml schemas, check it out as it's a great way to keep control of xml documents structure.
The code after update 2:
Feed class
import javax.xml.bind.annotation.*;
import java.util.List;
#XmlRootElement(name = "feed")
#XmlAccessorType(XmlAccessType.FIELD)
public class Feed {
#XmlElement(name = "entry")
private List<Entry> entries;
public List<Entry> getEntries() {
return this.entries;
}
}
Entry class
import javax.xml.bind.annotation.*;
import java.util.Date;
#XmlRootElement(name = "entry")
#XmlAccessorType(XmlAccessType.FIELD)
public class Entry {
#XmlElement(name = "title")
private String title;
#XmlElement(name = "id")
private String id;
#XmlElement(name = "published")
private Date datePublished;
#XmlElement(name = "author")
private Author author;
public String toString(){
return String.format("Id: %s, Title: %s, Author: %s, Published: %s",
id,
title,
author.toString(),
datePublished.toString());
}
}
Author class
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "author")
#XmlAccessorType(XmlAccessType.FIELD)
public class Author {
#XmlElement(name = "name")
private String name;
#XmlElement(name = "url")
private String url;
public String getName() {
return name;
}
public String getUrl() {
return url;
}
#Override
public String toString() {
return getName();
}
}
Main
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import java.io.File;
public class Main {
public static void main(String[] args) throws JAXBException {
Feed feed = (Feed) JAXBContext
.newInstance(Feed.class)
.createUnmarshaller()
.unmarshal(new File("youtube_feed.xml"));
for (Entry entry : feed.getEntries()) {
System.out.println(entry.toString());
}
}
}
Reading comprehension
JAXB and XML namespaces
Oracle JAXB annotations reference
Related
I'm trying to convert a Java bean into an xml document and I'm having trouble with some of these more complex interfaces. Here is the setup:
protected Set<Object> field1;
protected Map<Integer, List<Object>> field2;
protected List<String> field3;
protected List<Object> field4;
protected List<Object> field5;
protected List<Object> field6;
protected List<String> field7;
protected List<Object> field8;
In each Object (which is itself a bean) I have the following at the top of each class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"field1",
"field2",
"field3",
"field4",
"field5",
"field6",
"field7",
"field8"
})
#XmlRootElement(name = "root")
I keep getting an exception for the Map of Integers and Lists when I marshal the whole bean. Is there something that I'm missing?
Suppose you have below three class
Customer class
package comparison;
import java.util.ArrayList;
import java.util.List;
public class Customer {
private long id;
private String name;
private Address address;
private List<phonenumber> phoneNumbers;
public Customer() {
phoneNumbers = new ArrayList<PhoneNumber>();
}
}
Address class
package comparison;
public class Address {
private String city;
private String street;
}
and PhoneNumber class
package comparison;
public class PhoneNumber {
private String type;
private String number;
}
Now adding some dummy data
package comparison;
public class Data {
public static Customer CUSTOMER;
static {
CUSTOMER = new Customer();
CUSTOMER.setId(123);
CUSTOMER.setName("Jane Doe");
Address address = new Address();
address.setStreet("1 A Street");
address.setCity("Any Town");
CUSTOMER.setAddress(address);
PhoneNumber workPhoneNumber = new PhoneNumber();
workPhoneNumber.setType("work");
workPhoneNumber.setNumber("555-WORK");
CUSTOMER.getPhoneNumbers().add(workPhoneNumber);
PhoneNumber cellPhoneNumber = new PhoneNumber();
cellPhoneNumber.setType("cell");
cellPhoneNumber.setNumber("555-CELL");
CUSTOMER.getPhoneNumbers().add(cellPhoneNumber);
}
}
So now you apply marshalling to convert the object to xml
package comparison.jaxb;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
import comparison.Customer;
import static comparison.Data.CUSTOMER;
public class JAXBDemo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
JAXBElement<Customer> jaxbElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, CUSTOMER);
marshaller.marshal(jaxbElement, System.out);
}
}
A JAXBContext needs to be initialized on the binding metadata before
the marshal operation can occur.
Unlike XStream JAXB does not format
the XML by default, so we will enable this feature.
With no metadata
specified we need to supply JAXB with a root element name (and
namespace).
The code will produce result:
<customer>
<id>123</id>
<address>
<city>Any Town</city>
<street>1 A Street</street>
</address>
<name>Jane Doe</name>
<phoneNumbers>
<number>555-WORK</number>
<type>work</type>
</phoneNumbers>
<phoneNumbers>
<number>555-CELL</number>
<type>cell</type>
</phoneNumbers>
By default JAXB will access public fields and properties. You can configure JAXB to use field access with the following package level annotation.
#XmlAccessorType(XmlAccessType.FIELD)
package comparison;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
You can look at this blogpost for details.
I am trying to parse an xml to java objects, I've read and implemented the following tutorial:
http://www.vogella.com/articles/JAXB/article.html (works perfectly)
But when I create my own clases (similar to those in the tutorial)
I get: Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "clienteList"
Unless I use #XmlAccessorType(XmlAccessType.FIELD) on class Clientes but in the tutorial is not being used.
Any ideas ?
(It works fine with the #XmlAccessorType(XmlAccessType.FIELD) annotation but I want to know why is it being required with my classes while it is not for the classes in the tutorial)
Thank you in advance for any information.
Class Cliente
package mx.com.findep.crediseguros.dto.servicios.finsol;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "cliente")
public class Cliente {
private String numeroPersona;
#XmlElement(name = "numeroPersona")
public String getNumeroPersona() {
return numeroPersona;
}
public void setNumeroPersona(String numeroPersona) {
this.numeroPersona = numeroPersona;
}
}
Class Clientes
package mx.com.findep.crediseguros.dto.servicios.finsol;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "clientes")
//#XmlAccessorType(XmlAccessType.FIELD) //without this line it fails
public class Clientes {
// XmLElementWrapper generates a wrapper element around XML representation
#XmlElementWrapper(name = "clienteList")
// XmlElement sets the name of the entities
#XmlElement(name = "cliente")
private ArrayList<Cliente> clienteList;
public void setClienteList(ArrayList<Cliente> clienteList) {
this.clienteList = clienteList;
}
public ArrayList<Cliente> getClienteList() {
return clienteList;
}
}
Testing My Marshalling
package mx.com.findep.crediseguros.dto.servicios.finsol;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class TestClientesXml {
private static final String SOME_XML = "C:/bea/user_projects/domains/DominioDesarrollo/esquemas/calculoCostoSeguroPeticion.xml";
public static void main(String[] args) throws JAXBException, IOException {
ArrayList<Cliente> clienteList = new ArrayList<Cliente>();
Cliente cliente1 = new Cliente();
cliente1.setNumeroPersona("1");
clienteList.add(cliente1);
Cliente cliente2 = new Cliente();
cliente2.setNumeroPersona("2");
clienteList.add(cliente2);
Clientes clientes = new Clientes();
clientes.setClienteList(clienteList);
JAXBContext context = JAXBContext.newInstance(Clientes.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(clientes, System.out);
m.marshal(clientes, new File(SOME_XML));
System.out.println();
System.out.println("Output from our XML File: ");
Unmarshaller um = context.createUnmarshaller();
Clientes clientes2 = (Clientes) um.unmarshal(new FileReader(SOME_XML));
ArrayList<Cliente> list = clientes2.getClienteList();
for (Cliente cliente : list) {
System.out.println("Cliente: " + cliente.getNumeroPersona());
}
}
}
By default JAXB treats public fields and properties as mapped. If you annotate a field it then considers the field and property as mapped causing the conflict. Without #XmlAccessorType(XmlAccessType.FIELD) you should annotate the get or set method.
For More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
So lets say we have:
#XmlRootElement(name = "book")
public class Book {
#XmlElement(name = "book_title")
private String title;
public getTitle(){..}
public setTitle(){...}
}
if we run the code we will have
Exception in thread "main"
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "title"
this problem is related to the following location:
at public java.lang.String com.example.jaxb.Book.getTitle()
at com.example.jaxb.Book
this problem is related to the following location:
at private java.lang.String com.example.jaxb.Book.title
at com.example.jaxb.Book
But if we add the annotation: XmlAccessorType
#XmlRootElement(name = "book")
#XmlAccessorType(XmlAccessType.FIELD)
public class Book {
the error will disappear.
When have class which want to marshall and have 10 fields, I prefer to annotate only fields, not one time the setter then the getter. So use #XmlAccessorType and annotate only the fields.
Sorry for the title I can't think of a good way to explain what I need.
I am trying to create an xml file which will be picked up by a system to run through some orders but I am getting stuck on how to create the file correctly.
The file contains:
an order number, each order number can then have multiple order lines, each order line has a product and each product has a quantity.
for example
<ORDER="123">
<ORDER_LINE="1" product="abc" QUANTITY="1"/>
<ORDER_LINE="2" product="def" QUANTITY="2"/>
</ORDER>
<ORDER="456">
<ORDER_LINE="3" product="ghi" QUANTITY="3"/>
<ORDER_LINE="4" product="jkl" QUANTITY="4"/>
<ORDER_LINE="5" product="mno" QUANTITY="2"/>
</ORDER>
I've written a helper that I want to pass in all the information and then create the xml. The problem is I am confused as to how to determine where 1 order ends and the next begins.
I was going to send all the order ids in a list, all the orderlines in another etc but then I won't know when I get to the end of one order.
In the example above order 123 has 2 products where has order 456 has 3 so it's not a case of just dividing the orderIDs by the rest of the list size.
Can anybody suggest a way I can do this?
I want my helper to be as easy to call as possible and not have to rely on orders being a certain length.
Your 'Helper' probably should be a Builder. I suggest the following API
new OderBuilder()
.startOrder(123) // starts a new order and finishes the first
.addLineItem("abc",1)
.addLineItem("def",2)
.createXml(); // actually writes out the xml or returns it, or what ever you want
See key is to create a fluent API by returning the Builder itself on each method call.
Inside the Builder you might want to create objects for Orders and OrderItems.
First of all, I want to point out that your example isn't an xml file: there is no root element and I guess that <ORDER="123"> and <ORDER_LINE="3"> are supposed to be something like <ORDER ID="123"> and <ORDER_LINE ID="3">.
Secondly, if I had to create an xml file, I would use the JAXB library and annotations:
I have created a class Order that contains all the information about the ORDER (it has a reference to a list of OrderLine):
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.FIELD)
public class Order {
#XmlAttribute(name="ID")
private String id;
#XmlElement(name="ORDER_LINE")
private List<OrderLine> orderLineList = new ArrayList<OrderLine>();
public Order(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<OrderLine> getOrderLineList() {
return orderLineList;
}
public void setOrderLineList(List<OrderLine> orderLineList) {
this.orderLineList = orderLineList;
}
public Order addOrderLine(OrderLine orderLine) {
orderLineList.add(orderLine);
return this;
}
}
Then I have created a class OrderLine that contains all the information about the ORDER_LINE:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
#XmlAccessorType(XmlAccessType.FIELD)
public class OrderLine {
#XmlAttribute(name="ID")
private String id;
#XmlAttribute(name="product")
private String product;
#XmlAttribute(name="QUANTITY")
private String quantity;
public OrderLine(String id, String product, String quantity) {
this.id = id;
this.product = product;
this.quantity = quantity;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
}
Finally I have created a class Orders that will be the root element of my xml file:
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="ORDERS")
public class Orders {
#XmlElement(name="ORDER")
List<Order> orderList = new ArrayList<Order>();
public List<Order> getOrderList() {
return orderList;
}
public Orders addOrder(Order order) {
orderList.add(order);
return this;
}
public static void main(String[] args) {
Orders orders = new Orders()
.addOrder(new Order("123")
.addOrderLine(new OrderLine("1", "abc", "1"))
.addOrderLine(new OrderLine("2", "def", "2")))
.addOrder(new Order("456")
.addOrderLine(new OrderLine("3", "ghi", "3"))
.addOrderLine(new OrderLine("4", "jkl", "4"))
.addOrderLine(new OrderLine("5", "mno", "2")));
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Orders.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(orders, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
In the main method I just create an instance of Orders and populate it with the required information. After that I just use methods from the JAXB library.
The output is the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ORDERS>
<ORDER ID="123">
<ORDER_LINE ID="1" product="abc" QUANTITY="1"/>
<ORDER_LINE ID="2" product="def" QUANTITY="2"/>
</ORDER>
<ORDER ID="456">
<ORDER_LINE ID="3" product="ghi" QUANTITY="3"/>
<ORDER_LINE ID="4" product="jkl" QUANTITY="4"/>
<ORDER_LINE ID="5" product="mno" QUANTITY="2"/>
</ORDER>
</ORDERS>
Hope this was helpful.
I have the following xml format that i want to bind it through a POJO and using JAXB annotations. The XML format is the following:
<datas>
<data>apple<data>
<data>banana<data>
<data>orange<data>
<datas>
And i'm trying to bind the data through the following POJO:
#XmlRootElement()
#XmlAccessorType(XmlAccessType.FIELD)
public class Datas {
#XmlElement
private List<String> data;
//get/set methods
}
And also i try and this POJO:
#XmlRootElement()
#XmlAccessorType(XmlAccessType.FIELD)
public class Datas {
#XmlElement
private List<Data> datas;
//get/set methods
}
//
#XmlRootElement()
#XmlAccessorType(XmlAccessType.FIELD)
public class Data{
#XmlElement
private String data;
//get/set methods
}
In the first case it retrieves only the first data: apple. In the second case doesn't retrieve anything. Could someone help me to provide the appropriate POJO and annotations in order to bind all data?
You can do one of the following options:
OPTION #1
Datas
package forum11311374;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Datas {
private List<String> data;
//get/set methods
}
For More Information
http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html
OPTION #2
Datas
package forum11311374;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Datas {
#XmlElement(name="data")
private List<Data> datas;
//get/set methods
}
Data
package forum11311374;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class Data{
#XmlValue
private String data;
//get/set methods
}
For More Information
http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html
The following can be used with both options:
input.xml/Ouput
I have updated the XML document to contain the necessary closing tags. <data>apple</data> instead of <data>apple<data>.
<datas>
<data>apple</data>
<data>banana</data>
<data>orange</data>
</datas>
Demo
package forum11311374;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Datas.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum11311374/input.xml");
Datas datas = (Datas) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(datas, System.out);
}
}
The first option did work for me... not sure why you are getting the problem...
Try this annotation...
#XmlElements(#XmlElement(name="data", type=String.class))
private List<String> datas; //ignore the variable name
I went through almost all questions related to this topic here. But was not able to get a proper solution.
My issue is as follows:
I created a simple program to unmarshall an xml file for which i had a xsd. I was able to do that successfully. But if i am getting an xml without xsd, how can I get my attributes from that, if the xml looks something like this :
<items>
<item>
<code>12000</code>
<name>Samsung 620</name>
<price>9999</price>
</item>
<item>
<code>15000</code>
<name>NOKIA</name>
<price>19999</price>
</item>
<item>
<code>18000</code>
<name>HTC 620</name>
<price>29999</price>
</item>
</items>
Here I don't have an xsd to generate my classes. How can i proceed? Kindly help me.
Thank You
Below is one way that you could map your use case with a JAXB (JSR-222) implementation:
Items
We will use the following class for the root object and annotate it with #XmlRootElement. The #XmlRootElement annotation tells JAXB that this class should be instantiated if the root element in the document being unmarshalled is items, you can also specify a different name #XmlRootElement(name="foo").
package forum11152046;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
public class Items {
private List<Item> items;
#XmlElement(name="item")
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
}
Item
In this example I created a class where all the property names correspond directly to the names in the XML document. This means there aren't any annotations that need to be added. If you need to override the default name you can use an annotation such as #XmlElement to do so. I used the #XmlElement annotation to do this in the Items class for the items property.
package forum11152046;
public class Item {
private int code;
private String name;
private int price;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
Demo
package forum11152046;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Items.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum11152046/input.xml");
Items items = (Items) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(items, System.out);
}
}
input.xml/Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items>
<item>
<code>12000</code>
<name>Samsung 620</name>
<price>9999</price>
</item>
<item>
<code>15000</code>
<name>NOKIA</name>
<price>19999</price>
</item>
<item>
<code>18000</code>
<name>HTC 620</name>
<price>29999</price>
</item>
</items>
If you want to stick with JAXB, you can either write an XML Schema Document on your own to validate such XML (it looks simple but it's just an instance, you need to find out what could change in these documente beforehand) or create a POJO with JAXB annotations matching these nodes. I'm afraid there's no other way. You still have to know well what the format allows.