3

I want to map a XML (which is basically exported from some database) file to java objects using JAXB.

My target XML is like-

<database name="sales">
    <table name="product">
        <column name="id">1</column>
        <column name="name">Product 1</column>
        <column name="qty">10</column>
    </table>
    <table name="product">
        <column name="id">2</column>
        <column name="name">Product 2</column>
        <column name="qty">20</column>
    </table>
</database>

And I am expecting a Model like below:

public class Product {
  int id;
  String name;
  int qty;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getQty() {
    return qty;
  }

  public void setQty(int qty) {
    this.qty = qty;
  }
}

And

public class Sales {
  List<Product> products;

  public List<Product> getProducts() {
    return products;
  }

  public void setProducts(List<Product> products) {
    this.products = products;
  }
}

Some Unmarshelling example that match my requirement will be very helpful. Can anyone please help me?

6
  • I want to unmarshall the xml to my desired java models. Commented Jan 2, 2015 at 9:03
  • Are you finding any problem while unmarshaling or you want any example of unmarshaling ? Commented Jan 2, 2015 at 9:05
  • mkyong.com/java/jaxb-hello-world-example Commented Jan 2, 2015 at 9:16
  • Thanks looser! already saw the example but that doesn't match my requirements Commented Jan 2, 2015 at 9:20
  • Probably this answer will help you which unmarshall to List. stackoverflow.com/questions/25704853/… Commented Jan 2, 2015 at 9:31

2 Answers 2

1

Final EDIT:

You need to add following to your classes:

Modify Sales Class to:

   /**
JMathur
 */

package com.org.test1;

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;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="database")
@XmlAccessorType(XmlAccessType.FIELD)
public class Sales {

@XmlElement(name="table")
List<Product> products;

@XmlAttribute(name="names")
private String sales;

public String getSales() {
    return sales;
}

public void setSales(String sales) {
    this.sales = sales;
}

public List<Product> getProducts() {
    return products;
}

public void setProducts(List<Product> products) {
    this.products = products;
}


}

Modify Product Class to:

    /**
JMathur
 */

package com.org.test1;

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;

@XmlAccessorType(XmlAccessType.FIELD)
public class Product {
@XmlAttribute(name="name")
private String tableName;


public String getTableName() {
    return tableName;
}

public void setTableName(String tableName) {
    this.tableName = tableName;
}


private  List<Column> column;


public List<Column> getColumn() {
    return column;
}

public void setColumn(List<Column> column) {
    this.column = column;
}



}

Then you will need add two more classes:

Column.java

 /**
JMathur
*/

package com.org.test1;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlAccessorType(XmlAccessType.FIELD)
public class Column {
@XmlValue
@XmlJavaTypeAdapter(AdapterDATA.class)
protected String value;

public String getValue() {
    return value;
}

public void setValue(String value) {
    this.value = value;
}

@XmlAttribute
protected String name;


public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}


}

AdapterDATA.java

package com.org.test1;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class AdapterDATA extends XmlAdapter<String, String> {

@Override
public String marshal(String arg0) throws Exception {
    return arg0;
}
@Override
public String unmarshal(String arg0) throws Exception {
    return arg0;
}

}

Then You can marshal and unmarhsal using following code

     /**
JMathur
*/

package com.org.test1;

import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
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.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

public class XMLBuilder {
public static void main(String args[]) {
    Sales object = new Sales();
    object.setSales("sales");

    Product p1 = new Product();
    Product p2 = new Product();

    Column c1 = new Column();
    Column c2 = new Column();
    Column c3 = new Column();
    c1.setName("id");
    c1.setValue("1");
    c2.setName("name");
    c2.setValue("Product_Name");
    c3.setName("qty");
    c3.setValue("10");

    List<Column> listColumn=new ArrayList<Column>();
    listColumn.add(c1);
    listColumn.add(c2);
    listColumn.add(c3);

    p1.setTableName("product");
    p1.setColumn(listColumn);

    p2.setTableName("product");
    p2.setColumn(listColumn);

    List<Product> list = new ArrayList<Product>();
    list.add(p1);
    list.add(p2);

    object.setProducts(list);

    String response=marshal(object);

    Sales salesAfterUnMarshal=(Sales)unmarshal(new StringReader(response), Sales.class);



    System.out.println("Marshalling====="+response);

    System.out.println("Unmarshalling==="+salesAfterUnMarshal.getProducts());
}

public static <T> String marshal(T object) {

    StringWriter response = new StringWriter();
    try {
        JAXBContext jaxbContext = JAXBContext
                .newInstance(object.getClass());
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        // output pretty printed
        jaxbMarshaller
                .setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);

        jaxbMarshaller.marshal(object, response);

    } catch (JAXBException jxbException) {
        throw new RuntimeException(jxbException.getMessage(), jxbException);
    }
    return response != null ? response.toString() : null;

}
public static <T> T unmarshal(Reader reader, Class<T> clazz) {
    T classInstance = null;
    try {
        JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        Object object = unmarshaller.unmarshal(new StreamSource(reader));
        classInstance = clazz.cast(object);
    } catch (JAXBException jxbException) {
    //  throw new RuntimeException(errorMessage, jxbException);
    }
    catch (Exception jxbException) {
    //  throw new RuntimeException(errorMessage, jxbException);
    }
    return classInstance;
}
}

You output would be:

Marshalling=====<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Database names="sales">
<table name="product">
    <column name="id">1</column>
    <column name="name">Product_Name</column>
    <column name="qty">10</column>
</table>
<table name="product">
    <column name="id">1</column>
    <column name="name">Product_Name</column>
    <column name="qty">10</column>
</table>
</Database>

Unmarshalling===[com.org.test1.Product@27d6c5e0, com.org.test1.Product@4f3f5b24]
Sign up to request clarification or add additional context in comments.

2 Comments

Output to above: Marshalling=====<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Sales> <products> <id>1</id> <name>List_item1</name> <qty>20</qty> </products> <products> <id>2</id> <name>List_item2</name> <qty>30</qty> </products> </Sales> Unmarshalling===[com.org.test1.Product@58372a00, com.org.test1.Product@4dd8dc3]
Thanks Jeet. From the Marshalling output I can see the generated XML is not like the one I mentioned on the post. Basically I want to map "id","name" and "qty" attributes of <column> element to java object field.
0

I think you need to change xml like:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<database name="sales">
 <table name="product">
    <id>1</id>
    <name>Product 1</name>
    <qty>10</qty>
 </table>
</database>

Than define the Product class like:

@XmlRootElement(name="table")
public class Product {
 int id;
 String name;
 int qty;

public int getId() {
    return id;
}
@XmlElement
public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getQty() {
    return qty;
}

public void setQty(int qty) {
    this.qty = qty;
}

 @Override
 public String toString() {
    return id+" "+ name +" "+qty;
 }
}

And Sales class like:

@XmlRootElement(name="database")
public class Sales {
List<Product> products;

@XmlElement(name="table")
public List<Product> getProducts() {
    return products;
}

public void setProducts(List<Product> products) {
    this.products = products;
}
}

After define Main class like:

public class Main {

public static void main(String[] args) {
    try {

        File file = new File("sales.xml");
        System.out.println(file);
        JAXBContext jaxbContext = JAXBContext.newInstance(Sales.class);

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        Sales sales = (Sales) jaxbUnmarshaller.unmarshal(file);

        List<Product> products= sales.getProducts();
        System.out.println(products.size());
        Product product= products.get(0);
        System.out.println(product);

    } catch (JAXBException e) {
        e.printStackTrace();
    }
}
}

It give me this output: 1 Product 1 10

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.