Using Smooks+Mule to transform CSV file to XML one

As I promised before here is an example of how to use Smooks in combination with Mule. In this example I transform a CSV file to a plain XML file. This XML file can then be transformed with an XSLT transformation to the desired XML format.
I start with the Smooks config file ‘smooks-csv-config.xml’:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
                      xmlns:csv="http://www.milyn.org/xsd/smooks/csv-1.2.xsd">
    <csv:reader fields="order_no?trim,cust_no?trim,prod_no?trim,amount?trim"
    separator="|" quote="'" skipLines="0" rootElementName="orders" recordElementName="order" indent="true" />
 
    <resource-config selector="global-parameters">
        <param name="stream.filter.type">SAX</param>
    </resource-config>
</smooks-resource-list>

The important part is in the ‘csv:reader fields’ attribute. Here I define the fields that can be expected in my input CSV file. As you can see I apply ‘?trim’ to the fields so additional spaces are removed.
My Mule config file ‘smooks-csv-config’ that is used for this test can be found here. The important part looks like:

1
2
3
4
5
6
<smooks:transformer
        name="csvToXmlSmooksTransformer"
        configFile="/transforms/smooks-csv-config.xml"
        resultType="STRING"
        reportPath="target/smooks-report/report.html"
        />

In the transformer the Smooks config file to be used is defined, so in this case I refer to the one I showed in at the beginning of this post. The next step is to create the test class.:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package nl.redstream.mule.test;
 
import java.io.File;
import java.io.InputStream;
import java.util.Locale;
import java.util.TimeZone;
 
import org.junit.Test;
import org.mule.DefaultMuleMessage;
import org.mule.api.MuleMessage;
import org.mule.module.client.MuleClient;
import org.mule.tck.FunctionalTestCase;
import org.mule.util.IOUtils;
 
public class SmooksCsvTest extends FunctionalTestCase
{
	@Override
	protected String getConfigResources() {
		return "config/smooks-csv-config.xml";
	}
 
	@Test
	public void testSmooks() throws Exception {
		InputStream in = IOUtils.getResourceAsStream("test-order.csv", this.getClass());
 
		MuleClient client = new MuleClient();
		MuleMessage reply = client.send("vm://test-csv-to-xml",new DefaultMuleMessage(in));
 
		assertNotNull(reply);
		assertNotNull(reply.getPayload());
 
		Object payload = reply.getPayload();
		assertTrue("The message payload is not an instance of String", payload instanceof String);
		assertTrue("The report file wasn't created", getReportFile().exists());
	}
 
	private File getReportFile() {
		return new File("target/smooks-report/report.html");
	}
	private void deleteReportFile() {
		getReportFile().delete();
	}
 
	/* (non-Javadoc)
	 * @see org.mule.tck.AbstractMuleTestCase#doSetUp()
	 */
	@Override
	protected void doSetUp() throws Exception {
		super.doSetUp();
 
		TimeZone.setDefault(TimeZone.getTimeZone("EST"));
		Locale.setDefault(new Locale("en","IE"));
		deleteReportFile();
	}
 
	/* (non-Javadoc)
	 * @see org.mule.tck.AbstractMuleTestCase#doTearDown()
	 */
	@Override
	protected void doTearDown() throws Exception {
		super.doTearDown();
		deleteReportFile();
	}
}

In the file I read the CSV file and put it on the inbound endpoint. The Smooks transformer is then applied to it and the result is passed to the STDIO outbound. So as a result I expect XML output in my console. The CSV file I used for testing looks like:

1888852| 21625|02745011|31|
1888853| 21625|02745011|71|
1888854| 21625|02745011| 3|

And the result in my console contains:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<orders>
        <order number="1">
                <order_no>1888852</order_no>
                <cust_no>21625</cust_no>
                <prod_no>02745011</prod_no>
                <amount>31</amount>
        </order>
        <order number="2">
                <order_no>1888853</order_no>
                <cust_no>21625</cust_no>
                <prod_no>02745011</prod_no>
                <amount>71</amount>
        </order>
        <order number="3">
                <order_no>1888854</order_no>
                <cust_no>21625</cust_no>
                <prod_no>02745011</prod_no>
                <amount>3</amount>
        </order>
</orders>

Of course this generated XML is very basic but it can be the base for the next (XSLT) transformation step as I said earlier in this post to create a more advanced XML matching your needs.

tags: ,

About Pascal Alma

Pascal started as an Oracle Developer in 1997 and developed numerous applications with Oracle Designer/Developer and PL/SQL. Since 2001 Pascal becomes more and more active with the development of software at the Java/J2EE platform. Nowadays Pascal is a senior JEE Developer/ Architect and has a lot of experience with several open source initiatives/ frameworks especially within the Enterprise Integration area. Besides these technical skills Pascal is a big Scrum enthusiastic.