Showing posts with label CSV to XML. Show all posts
Showing posts with label CSV to XML. Show all posts

Friday, July 20, 2012

Converting CSV to XML With Camel Bindy


Converting CSV file to XML using Apache Camel.


Why Apache Camel?
Because Camel Rocks :). Camel has huge transformation libraries which makes code easier and simple to understand and execute. Also Camel is free. It’s an open-source tool with huge user base and nice support. 

What’s the Corporate Problem?
Converting CSV to XML is common problem across IT industry where CSV might be the input imported by user and Web-Service might be expecting XML formatted data to run the business logic. Here we will do this conversion in two steps, and both the steps are useful for applicable applications.
Step 1. Converting CSV file to POJO objects (Beans)
Step 2. Converting POJO list to XML using xstream (Open Source easy to use Jar file)
If you are just interested in POJO list, please stop at first step.

Can you run through any example?

Sure thing. Let’s consider we have Employee.csv file having data like below.
employeeId,firstName,lastName,role
23445,Ambarish,Deshpande,Java Lead
23411,Paul,Bulson,Team Member

First we need a bean (DTO) class to map CSV fields. Getters / Setters are optional here.

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@CsvRecord(separator = ",", skipFirstLine = true)
public class EmployeeDTO implements Serializable{
@XmlAttribute
      @DataField(pos = 1)
      private int employeeId;
      @XmlAttribute
      @DataField(pos = 2)
      private String firstName;
      @XmlAttribute
      @DataField(pos = 3)
      private String lastName;
      @XmlAttribute
      @DataField(pos = 4)
      private String role;
}

Annotations?

All @XML* annotations are coming from javax.xml.bind.annotation.* package.
For @CSVRecord and @DataField you have import camel-bindy.jar. I have listed all the dependencies in Appendix section at last.

Now, for actual conversion, camel route must be created.

public class ConvertorRoute implements RoutesBuilder{
     
@Override
public void addRoutesToCamelContext(CamelContext context) throws Exception {
  context.addRoutes(new RouteBuilder() {
public void configure() {
  try {
            DataFormat bindy = new BindyCsvDataFormat("com.package.dto");
                  from("file://TEST?fileName=Employee.csv").
                  unmarshal(bindy).
                  marshal().
                  xstream().
                  to("file://TESTOUT?fileName=employee.xml");
            } catch (Exception e) {
                        e.printStackTrace();
            }
         }
     });
}

public static void main(String[] args) { 
 try{
CamelContext context = new DefaultCamelContext();
      ConvertorRoute route = new ConvertorRoute();
      route.addRoutesToCamelContext(context);
      context.start();
      Thread.sleep(5000);
      context.stop();
  }catch(Exception exe){
      exe.printStackTrace();
}

}

Steps in Route:

1.    Register Bean package (where DTO class resides) with BindyCSVDataFormat.

    DataFormat bindy = new BindyCsvDataFormat("com.package.dto");

2.    Pick Up the file from TEST folder. (Root//TEST)
3.    Unmarshal the csv file with register Bindy. This step creates a List of EmployeeDTO. If intended output is achieved here. Please use this output further.
4.    Marshal().xstream() will convert this DTO List to XML and finally
5.    Output file will be written on TESTOUT folder as employee.xml file.


Employee.XML file:             


<?xml version="1.0" ?>
<list>
<map>
<entry>
  <string>com.thd.eai.dto.EmployeeDTO</string>
<com.thd.eai.dto.EmployeeDTO>
      <employeeId>23445</employeeId>
    <firstName>Ambarish</firstName>
      <lastName>Deshpande</lastName>
      <role>Lead Java</role>
   </com.thd.eai.dto.EmployeeDTO>
  </entry>
 </map>
<map>
 <entry>
  <string>com.thd.eai.dto.EmployeeDTO</string>
<com.thd.eai.dto.EmployeeDTO>
      <employeeId>23411</employeeId>
      <firstName>Paul</firstName>
      <lastName>Bulson</lastName>
      <role>Team Member</role>
   </com.thd.eai.dto.EmployeeDTO>
 </entry>
</map>
</list>



Appendix and References:

List of dependencies: 

camel-bindy-2.9.0.jar,
camel-core-2.9.0.jar,
camel-csv-2.9.0.jar,
camel-xstream-2.9.0.jar, 
slf4j-api-1.6.4.jar,
slf4j-log4j12-1.6.4.jar,
solr-commons-csv-1.3.0.jar,
xstream-1.3.1 

Important Links:

Tuesday, May 15, 2012

CSV to XML transformation using Camel

Lots of Projects I know needs this transformation.
CSV to XML, where you might be reading user uploaded CSV file or it can be Pipe delimited flat file and make a XML out of it.
Below is the code doing this using camel and Xstream. I am exploring more to get XML nodes to populate as headers, but not yet successful. I will update that as soon as I get the solution. till then.. this is the good code u can use.

 

package com.XYZ;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class FileCSVtoXMLConversion {
private static XStream xStream;
public static void main(String args[]) throws Exception {
// create CamelContext
CamelContext context = new DefaultCamelContext();
xStream = new XStream(new DomDriver());
// add our route to the CamelContext
context.addRoutes(new RouteBuilder() {
public void configure() {
from("
file://Some/TEST?fileName=ArticleTest.csv").
unmarshal().
csv().
process(new Processor() {
  @Override
  public void process(Exchange exchange) throws Exception {
    String xmlConverted = xStream.toXML(exchange.getIn().getBody());
    exchange.getIn().setBody(xmlConverted);
  }
 }
).to("
file://Some/TESTOUT?fileName=ArticleTest.XML");
}
});
// start the route and let it do its work
context.start();
Thread.sleep(10000);
// stop the CamelContext
context.stop();
}
}