Transforming inline with XQuery

Camel supports the use of Camel's XQuery Expression Language along with the transform statement as a quick and easy way to transform an XML message within a route.

This recipe will show you how to use an XQuery Expression to do in-route XML transformation.

Getting ready

The Java code for this recipe is located in the org.camelcookbook.transformation.xquery package. Spring XML files are located under src/main/resources/META-INF/spring and prefixed with xquery.

To use the XQuery Expression Language, you need to add a dependency element for the camel-saxon library, which provides the implementation for the XQuery Expression Language.

Add the following to the dependencies section of your Maven POM:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-saxon</artifactId>
  <version>${camel-version}</version>
</dependency>

How to do it...

In the Camel route, specify a transform statement followed by the XQuery Expression Language code to do your transformation.

In the XML DSL, this is written as:

<route>
  <from uri="direct:start"/>
  <transform>
    <xquery>
      &lt;books&gt;{
        for $x in /bookstore/book
        where $x/price>30
        order by $x/title
        return $x/title
      }&lt;/books&gt;
    </xquery>
  </transform>
</route>

Note

When using the XML DSL, remember to XML encode the XQuery embedded XML elements. Therefore, < becomes &lt; and > becomes &gt;.

In the Java DSL, the same route is expressed as:

from("direct:start")
  .transform(xquery("<books>{ for $x in /bookstore/book "
                  + "where $x/price>30 order by $x/title "
                  + "return $x/title }</books>"));

Feed the following input XML message through the transformation:

<bookstore>
  <book category="COOKING">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="CHILDREN">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="PROGRAMMING">
    <title lang="en">Apache Camel Developer's Cookbook</title>
    <author>Scott Cranton</author>
    <author>Jakub Korab</author>
    <year>2013</year>
    <price>49.99</price>
  </book>
  <book category="WEB">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

The resulting message will be:

<books>
  <title lang="en">Apache Camel Developer's Cookbook</title>
  <title lang="en">Learning XML</title>
</books>

The processing step after the transform statement will see the transformed message content in the body of the exchange.

How it works...

Camel's XQuery Expression Language is a good way to inline XML transformation code within your route. The result of the XQuery Expression becomes the new message body after the transform step.

All of the message's body, headers, and properties are made available to the XQuery Processor, so you can reference them directly within your XQuery statement. This provides you with a powerful mechanism for transforming XML messages. If you are more comfortable with XSLT, take a look at the Transforming with XSLT recipe.

Tip

In-lining the transformation within your integration route can sometimes be an advantage as you can clearly see what is being changed. However, when the transformation expression becomes so complex that it starts to overwhelm the integration route, you may want to consider moving the transformation expression outside of the route.

See the Transforming using a Simple Expression recipe for another inline transformation example, and see the Transforming with XSLT recipe for an example of externalizing your transformation.

You can fetch the XQuery Expression from an external file using Camel's resource reference syntax. To reference an XQuery file on the classpath you can specify:

<transform>
  <xquery>resource:classpath:/path/to/myxquery.xml</xquery>
</transform>

This is equivalent to using XQuery as an endpoint:

<to uri="xquery:classpath:/path/to/myxquery.xml"/>

There's more...

The XQuery Expression Language allows you to pass in headers associated with the message. These will show up as XQuery variables that can be referenced within your XQuery statements. Consider, from the previous example, to allow the value of the books that are filtered to be passed in with the message body, that is, parameterize the XQuery, you can modify the XQuery statement as follows:

<transform>
  <xquery>
    declare variable $in.headers.myParamValue asxs:integer external;
    &lt;books value='{$in.headers.myParamValue}'&gt;{
      for $x in /bookstore/book
      where $x/price>$in.headers.myParamValue
      order by $x/title
      return $x/title
    }&lt;/books&gt;
  </xquery>
</transform>

Message headers will be associated with an XQuery variable called in.headers.<name of header>. To use this in your XQuery, you need to explicitly declare an external variable of the same name and XML Schema (xs:) type as the value of the message header.

The transform statement will work with any Expression Language enabled within Camel, so if you need more powerful message processing capabilities you can leverage scripting languages such as Groovy or JavaScript (among many others) as well. The Transforming using a Simple Expression recipe will show you how to use the Simple Expression Language to do transformations on String messages.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.148.105