I am trying to parse the below XML
using SimpleXML
parsing.
I have tried in different ways to parse the Attributes
of the Element
but unable to get success in parsing the below XML.
It generates an error that is list at the bottom.
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<order>
<id>1</id>
<id_address_delivery xlink:href="http://abc.com/add/1">1</id_address_delivery>
<id_address_invoice xlink:href="http://abc.com/add/2">2</id_address_invoice>
</order>
</prestashop>
Order.java
@Root(name="order")
@Namespace(reference="http://www.w3.org/1999/xlink",prefix="xlink")
public class Order {
@Element(name="id",required=true)
private int order_id;
@Element(name="id_address_delivery",required=false)
private int id_address_delivery;
@Attribute( name="href", required=false)
private String id_address_delivery_href;
@Element(name="id_address_invoice",required=false)
private int id_address_invoice;
@Attribute(name="href", required=false)
private String id_address_invoice_href;
}
OrderObject.java
public class OrderObject
{
@ElementList(required=true, inline=true)
private List<Order> list = new ArrayList<Order>();
public List<Order>getList()
{
return this.list;
}
}
Exception that I get is :
WARN/System.err(988): org.simpleframework.xml.core.PersistenceException:
Duplicate annotation of name 'href' on field 'id_address_delivery_href'
private java.lang.String com.prestashop.orders.Order.id_address_delivery_href
at org.simpleframework.xml.core.StructureBuilder.process(StructureBuilder.java:250)
at org.simpleframework.xml.core.StructureBuilder.process(StructureBuilder.java:173)
at org.simpleframework.xml.core.ObjectScanner.field(ObjectScanner.java:438)
at org.simpleframework.xml.core.ObjectScanner.scan(ObjectScanner.java:371)
at org.simpleframework.xml.core.ObjectScanner.<init>(ObjectScanner.java:82)
.
.
Step 1: Creating an XML file (Optional): Create an XML file which need to convert into the array. <? xml version = '1.0' ?> Step 2: Convert the file into string: XML file will import into PHP using file_get_contents() function which read the entire file as a string and store into a variable.
XML parsing is the process of reading an XML document and providing an interface to the user application for accessing the document. An XML parser is a software apparatus that accomplishes such tasks.
There are two ways to parse the file using 'ElementTree' module. The first is by using the parse() function and the second is fromstring() function. The parse () function parses XML document which is supplied as a file whereas, fromstring parses XML when supplied as a string i.e within triple quotes.
The reason for this exception are your both @Attribute
annotations. They aren't set to the next element but to the entire Order
object. Your annotations would set href
twice, but with different values.
Please see JavaDoc of @Attribute
:
The
Attribute
annotation represents a serializable XML attribute within an XML element. [...]
But there's a nice and simple solution: Instead of combining element and attribute, make a class which does this.
OrderObject
class:@Root(name = "prestashop")
@Namespace(reference = "http://www.w3.org/1999/xlink", prefix = "xlink")
public class OrderObject
{
@ElementList(required = true, inline = true)
private List<Order> list;
public OrderObject()
{
this.list = new ArrayList<>();
}
public List<Order> getList()
{
return list;
}
// ...
@Override
public String toString()
{
return "OrderObject{" + "list=" + list + '}';
}
}
Note: The toString()
methods in these classes are only implemented to check the result!
Order
class:@Root(name = "order")
public class Order
{
@Element(name = "id")
private int id;
@Element(name = "id_address_delivery")
private AdressDelivery delivery;
@Element(name = "id_address_invoice")
private AdressInvoice invoice;
public Order(int id, AdressDelivery delivery, AdressInvoice invoice)
{
this.id = id;
this.delivery = delivery;
this.invoice = invoice;
}
private Order() { }
// Getter / Setter etc.
@Override
public String toString()
{
return "Order{" + "id=" + id + ", delivery=" + delivery + ", invoice=" + invoice + '}';
}
@Root()
public static class AdressDelivery
{
@Namespace(reference = "http://www.w3.org/1999/xlink", prefix = "xlink")
@Attribute(name = "href", required = false)
private String link;
@Text()
private int value;
public AdressDelivery(String link, int value)
{
this.link = link;
this.value = value;
}
AdressDelivery() { }
// Getter / Setter etc.
@Override
public String toString()
{
return "AdressDelivery{" + "link=" + link + ", value=" + value + '}';
}
}
@Root()
public static class AdressInvoice
{
@Attribute(name = "href", required = false)
@Namespace(reference = "http://www.w3.org/1999/xlink", prefix = "xlink")
private String link;
@Text()
private int value;
public AdressInvoice(String link, int value)
{
this.link = link;
this.value = value;
}
AdressInvoice() { }
// Getter / Setter etc.
@Override
public String toString()
{
return "AdressInvoice{" + "link=" + link + ", value=" + value + '}';
}
}
}
You can see the AdressDelivery
and AdressInvoice
classes which combine attribute and element. You do not have to implement them as inner classes; feel free to write them as "normal" one. You also do not have to make them public, even private is possible (eg. construct them within the Order
's constructor.
But please note the empty constructors without arguments in Order
class (and it's inner classes). They are required. But you can make all of them private
- no need to expose them. It's only important that you have a constructor without arguments.
File f = new File("whatever.xml");
Serializer ser = new Persister();
OrderObject orderObject = ser.read(OrderObject.class, f);
System.out.println(orderObject);
This code parses the Xml from file and prints the deserialized object.
Input Xml (as in your question):
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<order>
<id>1</id>
<id_address_delivery xlink:href="http://abc.com/add/1">1</id_address_delivery>
<id_address_invoice xlink:href="http://abc.com/add/2">2</id_address_invoice>
</order>
</prestashop>
Result (from println()
):
OrderObject{list=[Order{id=1, delivery=AdressDelivery{link=http://abc.com/add/1, value=1}, invoice=AdressInvoice{link=http://abc.com/add/2, value=2}}]}
Not clearly represented, but enough to see the result :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With