Apache Camel Split XML File Example

0

In this article, we will see how to split XML file using Apache Camel split and XPath support.

This example uses the following frameworks:

  1. Maven 3.2.3
  2. Apache Camel 2.15.1
  3. Spring 4.1.5.RELEASE
  4. Eclipse  as the IDE, version Luna 4.4.1.

Dependencies

We are just relying camel’s core components, the spring based components and the logger component in case you want to log something so our pom.xml consists of:

  1. camel-core – camel core components like timer, bean etc
  2. slf4j-api – in case you want to use log
  3. slf4j-log4j12 – if you want to use log4j as the slf4j implementation
  4. camel-stream – for printing the messages to console
  5. spring-context and spring-core – for spring support
  6. camel-spring – include it if you want to define route in spring

Split XML file into various fragments using Apache Camel

In this example we will see how to split an XML file into various components using Apache Camel split and XPath functions.
Here is the XML that we want to split.

articles.xml:

<?xml version="1.0" encoding="UTF-8"?>
<articles>
  <article category="camel" title="Camel Splitter Example">
    <tags>camel,eia</tags>
    <authors>
    <author>John</author>
    </authors>
  </article>
  <article category="camel" title="Camel JMS Component">
    <tags>camel,jms</tags>
    <authors>
      <author>John</author>
      <author>Joe</author>
    </authors>
  </article>
  <article category="spring" title="Spring JdbcTemplate">
   <tags>spring,jdbc</tags>
    <authors>
      <author>Ram</author>
      <author>Dean</author>
    </authors>
  </article>
</articles>

Suppose you want to split the XML doc by <article> element, all you need to do is pass an XPath Expression within the split() DSL statement to isolate the nodes that you are interested in.
In this case we just want to split the XML doc into individual <article> elements.

from("direct:article")
.log("Split by article Element")
.split(xpath("/articles/article"))
.log("${body}")                    
.end();

CamelSplitXmlUsingXPathExample:

package com.javarticles.camel;

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class CamelSplitXmlUsingXPathExample {
    public static final void main(String[] args) throws Exception {
        CamelContext camelContext = new DefaultCamelContext();
        try {
            camelContext.addRoutes(new RouteBuilder() {
                public void configure() {
                    from("direct:articles")
                    .split(xpath("/articles"))
                        .log("${body}")
                        .multicast()    
                           .to("direct:article")                                          
                    .end();
                    
                    from("direct:article")
                    .log("Split by article Element")
                    .split(xpath("/articles/article"))
                        .log("${body}")                    
                    .end();
                }
            });
            ProducerTemplate template = camelContext.createProducerTemplate();
            camelContext.start();
            String filename = "target/classes/articles.xml";
            InputStream articleStream = new FileInputStream(filename);
            template.sendBody("direct:articles", articleStream);
        } finally {
            camelContext.stop();
        }
    }
}

Output:

Split by article Element
08:02| INFO | MarkerIgnoringBase.java 95 | <article category="camel" title="Camel Splitter Example">
    <tags>camel,eia</tags>
    <authors>
    <author>John</author>
    </authors>
  </article>
08:02| INFO | MarkerIgnoringBase.java 95 | <article category="camel" title="Camel JMS Component">
    <tags>camel,jms</tags>
    <authors>
      <author>John</author>
      <author>Joe</author>
    </authors>
  </article>
08:02| INFO | MarkerIgnoringBase.java 95 | <article category="spring" title="Spring JdbcTemplate">
   <tags>spring,jdbc</tags>
    <authors>
      <author>Ram</author>
      <author>Dean</author>
    </authors>
  </article>

The XPath expression passed to split() function will identify the
We will improve the split further to get the fragments by

    1. Category Attribute – The below DSL first splits the XML doc by <article> element and then sets the body to the category value. You may instead set it as a header.
      from("direct:category")
                          .log("Get categories for each article")
                          .split(xpath("/articles/article"))
                          .setBody(xpath("/article/@category").stringResult())
                              .log("${body}")
                           .end();   
      

 

  • Get tags for each article- Isolate the node values using XPath /articles/article/tags/text() and then call split() on the XPath expression.
    from("direct:tags")
                        .log("Get tags for each article")
                        .split(xpath("/articles/article/tags/text()"))
                        .log("${body}");      
                        
    
  • Get only the camel articles – XPath used is /articles/article[@category='camel'].
     from("direct:camelTitles")
                        .log("Get camel article titles")
                        .split(xpath("/articles/article[@category='camel']"))
                        .setBody(xpath("/article/@title"))
                        .log("${body}");
    

 

CamelSplitXmlUsingXPathExample:

package com.javarticles.camel;

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class CamelSplitXmlUsingXPathExample {
    public static final void main(String[] args) throws Exception {
        CamelContext camelContext = new DefaultCamelContext();
        try {
            camelContext.addRoutes(new RouteBuilder() {
                public void configure() {
                    from("direct:articles")
                    .split(xpath("/articles"))
                        .log("${body}")
                        .multicast()    
                           .to("direct:article") 
                           .to("direct:category") 
                           .to("direct:tags") 
                           .to("direct:camelTitles")                                          
                    .end();
                    
                    from("direct:article")
                    .log("Split by article Element")
                    .split(xpath("/articles/article"))
                        .log("${body}")                    
                    .end();
                    
                    from("direct:category")
                    .log("Get categories for each article")
                    .split(xpath("/articles/article"))
                    .setBody(xpath("/article/@category").stringResult())
                        .log("${body}")
                     .end();                    
                    
                    from("direct:tags")
                    .log("Get tags for each article")
                    .split(xpath("/articles/article/tags/text()"))
                    .log("${body}");      
                    
                    from("direct:camelTitles")
                    .log("Get camel article titles")
                    .split(xpath("/articles/article[@category='camel']"))
                    .setBody(xpath("/article/@title"))
                    .log("${body}");
                }
            });
            ProducerTemplate template = camelContext.createProducerTemplate();
            camelContext.start();
            String filename = "target/classes/articles.xml";
            InputStream articleStream = new FileInputStream(filename);
            template.sendBody("direct:articles", articleStream);
        } finally {
            camelContext.stop();
        }
    }
}

Output:

08:02| INFO | MarkerIgnoringBase.java 95 | <articles>
  <article category="camel" title="Camel Splitter Example">
    <tags>camel,eia</tags>
    <authors>
    <author>John</author>
    </authors>
  </article>
  <article category="camel" title="Camel JMS Component">
    <tags>camel,jms</tags>
    <authors>
      <author>John</author>
      <author>Joe</author>
    </authors>
  </article>
  <article category="spring" title="Spring JdbcTemplate">
   <tags>spring,jdbc</tags>
    <authors>
      <author>Ram</author>
      <author>Dean</author>
    </authors>
  </article>
</articles>
08:02| INFO | MarkerIgnoringBase.java 95 | Split by article Element
08:02| INFO | MarkerIgnoringBase.java 95 | <article category="camel" title="Camel Splitter Example">
    <tags>camel,eia</tags>
    <authors>
    <author>John</author>
    </authors>
  </article>
08:02| INFO | MarkerIgnoringBase.java 95 | <article category="camel" title="Camel JMS Component">
    <tags>camel,jms</tags>
    <authors>
      <author>John</author>
      <author>Joe</author>
    </authors>
  </article>
08:02| INFO | MarkerIgnoringBase.java 95 | <article category="spring" title="Spring JdbcTemplate">
   <tags>spring,jdbc</tags>
    <authors>
      <author>Ram</author>
      <author>Dean</author>
    </authors>
  </article>
08:02| INFO | MarkerIgnoringBase.java 95 | Get categories for each article
08:02| INFO | MarkerIgnoringBase.java 95 | camel
08:02| INFO | MarkerIgnoringBase.java 95 | camel
08:02| INFO | MarkerIgnoringBase.java 95 | spring
08:02| INFO | MarkerIgnoringBase.java 95 | Get tags for each article
08:02| INFO | MarkerIgnoringBase.java 95 | camel,eia
08:02| INFO | MarkerIgnoringBase.java 95 | camel,jms
08:02| INFO | MarkerIgnoringBase.java 95 | spring,jdbc
08:02| INFO | MarkerIgnoringBase.java 95 | Get camel article titles
08:02| INFO | MarkerIgnoringBase.java 95 | Camel Splitter Example
08:02| INFO | MarkerIgnoringBase.java 95 | Camel JMS Component

Split XML File with Namespace

In this example, we will use an XML with namespace http://www.javarticles.com/schema/articles.

articles.xml:

<?xml version="1.0" encoding="UTF-8"?>
<articles xmlns="http://www.javarticles.com/schema/articles">
  <article category="camel" title="Camel Splitter Example">
    <tags>camel,eia</tags>
    <authors>
    <author>John</author>
    </authors>
  </article>
  <article category="camel" title="Camel JMS Component">
    <tags>camel,jms</tags>
    <authors>
      <author>John</author>
      <author>Joe</author>
    </authors>
  </article>
  <article category="spring" title="Spring JdbcTemplate">
   <tags>spring,jdbc</tags>
    <authors>
      <author>Ram</author>
      <author>Dean</author>
    </authors>
  </article>
</articles>

We will associate the namespace URI and that a prefix.

from("direct:article")
                    .log("Split by article Element")
                    .split(xpath("/c:articles/c:article").namespace("c", "http://www.javarticles.com/schema/articles"))
                        .log("${body}")                    
                    .end();   

CamelSplitXmlNamespaceExample:

package com.javarticles.camel;

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class CamelSplitXmlNamespaceExample {
    public static final void main(String[] args) throws Exception {
        CamelContext camelContext = new DefaultCamelContext();
        try {
            camelContext.addRoutes(new RouteBuilder() {
                public void configure() {
                    from("direct:article")
                    .log("Split by article Element")
                    .split(xpath("/c:articles/c:article").namespace("c", "http://www.javarticles.com/schema/articles"))
                        .log("${body}")                    
                    .end();                    
                }
            });
            ProducerTemplate template = camelContext.createProducerTemplate();
            camelContext.start();
            String filename = "target/classes/articlesNs.xml";
            InputStream articleStream = new FileInputStream(filename);
            template.sendBody("direct:article", articleStream);
        } finally {
            camelContext.stop();
        }
    }
}

Output:

08:10| INFO | MarkerIgnoringBase.java 95 | <article category="camel" title="Camel Splitter Example" xmlns="http://www.javarticles.com/schema/articles">
    <tags>camel,eia</tags>
    <authors>
    <author>John</author>
    </authors>
  </article>
08:10| INFO | MarkerIgnoringBase.java 95 | <article category="camel" title="Camel JMS Component" xmlns="http://www.javarticles.com/schema/articles">
    <tags>camel,jms</tags>
    <authors>
      <author>John</author>
      <author>Joe</author>
    </authors>
  </article>
08:10| INFO | MarkerIgnoringBase.java 95 | <article category="spring" title="Spring JdbcTemplate" xmlns="http://www.javarticles.com/schema/articles">
   <tags>spring,jdbc</tags>
    <authors>
      <author>Ram</author>
      <author>Dean</author>
    </authors>
  </article>

Split using Camel spring

In this example, we will achieve the same using spring DSL. In order to split, we will use <split> element. The XPath will be included as <xpath> child element.

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
       ">
	<camelContext xmlns="http://camel.apache.org/schema/spring"
		xmlns:c="http://www.javarticles.com/schema/articles">
		<route>
			<from uri="direct:article" />
			<log message="Split by article Element"/>
			<split>
				<xpath>/c:articles/c:article</xpath>
				<log message="${body}"/>
			</split>
		</route>
	</camelContext>

</beans>

CamelSplitXmlUsingSpringDSL:

package com.javarticles.camel;

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.spring.SpringCamelContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class CamelSplitXmlUsingSpringDSL {
    public static final void main(String[] args) throws Exception {
        ApplicationContext appContext = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        CamelContext camelContext = SpringCamelContext.springCamelContext(
                appContext, false);
        try {            
            camelContext.start();
            ProducerTemplate template = camelContext.createProducerTemplate();
            camelContext.start();
            String filename = "target/classes/articlesNs.xml";
            InputStream articleStream = new FileInputStream(filename);
            template.sendBody("direct:article", articleStream);
        } finally {
            camelContext.stop();
        }
    }
}

Output:

08:10| INFO | MarkerIgnoringBase.java 95 | <article category="camel" title="Camel Splitter Example" xmlns="http://www.javarticles.com/schema/articles">
    <tags>camel,eia</tags>
    <authors>
    <author>John</author>
    </authors>
  </article>
08:10| INFO | MarkerIgnoringBase.java 95 | <article category="camel" title="Camel JMS Component" xmlns="http://www.javarticles.com/schema/articles">
    <tags>camel,jms</tags>
    <authors>
      <author>John</author>
      <author>Joe</author>
    </authors>
  </article>
08:10| INFO | MarkerIgnoringBase.java 95 | <article category="spring" title="Spring JdbcTemplate" xmlns="http://www.javarticles.com/schema/articles">
   <tags>spring,jdbc</tags>
    <authors>
      <author>Ram</author>
      <author>Dean</author>
    </authors>
  </article>

Download source code

This was an example about splitting XML using Camel XPath and Split support.

You can download the source code here: camelSplitXmlExample.zip
Share.

Comments are closed.