Files
spring-integration/src/reference/docbook/xml.xml
Artem Bilan 88de8117aa INT-3140: Add #xpath() SpEL Function Support
JIRA: https://jira.springsource.org/browse/INT-3140

* Introduce `XPathUtils`
* Add `#xpath()` tests
* Add documentation

INT-3140: Polishing according PR comments

INT-3140 Polishing

- Doc and javadoc polishing
- Fix some compiler warnings (not all xpath)
2013-11-15 15:54:14 -05:00

1386 lines
75 KiB
XML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="xml"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>XML Support - Dealing with XML Payloads</title>
<section id="xml-intro">
<title>Introduction</title>
<para>
Spring Integration's XML support extends the core of Spring Integration with
the following components:
</para>
<itemizedlist>
<listitem>
<para><emphasis><link linkend='xml-transformation'>Marshalling Transformer</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xml-transformation'>Unmarshalling Transformer</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xml-transformation'>Xslt Transformer</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xml-xpath-transformer'>XPath Transformer</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xml-xpath-splitting'>XPath Splitter</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xml-xpath-routing'>XPath Router</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xml-xpath-header-enricher'>XPath Header Enricher</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xml-xpath-filter'>XPath Filter</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xpath-spel-function'>#xpath SpEL Function</link></emphasis></para>
</listitem>
<listitem>
<para><emphasis><link linkend='xml-validating-filter'>Validating Filter</link></emphasis></para>
</listitem>
</itemizedlist>
<para>
These components are designed to make working with XML messages in Spring Integration simple.
The provided messaging components are designed to work with XML represented
in a range of formats including instances of
<classname>java.lang.String</classname>, <interfacename>org.w3c.dom.Document</interfacename>
and <interfacename>javax.xml.transform.Source</interfacename>. It should be noted however that
where a DOM representation is required, for example in order to evaluate an XPath expression,
the <classname>String</classname> payload will be converted into the required type and then
converted back again to <classname>String</classname>. Components that require an instance of
<interfacename>DocumentBuilder</interfacename> will create a namespace-aware instance if one is
not provided. In cases where you require greater control over document creation, you can
provide an appropriately configured instance of <interfacename>DocumentBuilder</interfacename>.
</para>
</section>
<section id="xpath-namespace-support">
<title>Namespace Support</title>
<para>
All components within the Spring Integration XML module provide namespace
support. In order to enable namespace support, you need to import the respective
schema for the Spring Integration XML Module. A typical setup is shown below:
</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-xml="http://www.springframework.org/schema/integration/xml"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/xml
http://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd">
</beans>]]></programlisting>
<section id="xml-xpath-expressions">
<title>XPath Expressions</title>
<para>
Many of the components within the Spring Integration XML module work
with XPath Expressions. Each of those components will either reference
an XPath Expression that has been defined as top-level element or via
a nested <code>&lt;xpath-expression/&gt;</code> element.
</para>
<para>
All forms of XPath expressions result in the creation of an
<interfacename>XPathExpression</interfacename> using the Spring
<classname>org.springframework.xml.xpath.XPathExpressionFactory</classname>.
When creating XPath expressions, the best XPath implementation that
is available on the classpath is being used, either JAXP 1.3+ or Jaxen,
whereby JAXP is preferred.
</para>
<note>
Spring Integration under the covers uses the XPath functionality as
provided by the <emphasis>Spring Web Services</emphasis> project
(http://www.springsource.org/spring-web-services). Specifically,
Spring Web Services' XML module (spring-xml-x.x.x.jar) is being used.
Therefore, for a deeper understanding, please refer to the respective
documentation as well at:
<itemizedlist>
<listitem>
<ulink url="http://static.springsource.org/spring-ws/sites/2.0/reference/html/common.html#xpath">
http://static.springsource.org/spring-ws/sites/2.0/reference/html/common.html#xpath
</ulink>
</listitem>
</itemizedlist>
</note>
<para>
Here is an overview of all available configuration parameters of the
<code>xpath-expression</code> element:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-expression expression=""]]><co id="xpath-expression-xml01-co" linkends="xpath-expression-xml01" /><![CDATA[
id="" ]]><co id="xpath-expression-xml02-co" linkends="xpath-expression-xml02" /><![CDATA[
namespace-map="" ]]><co id="xpath-expression-xml03-co" linkends="xpath-expression-xml03" /><![CDATA[
ns-prefix="" ]]><co id="xpath-expression-xml04-co" linkends="xpath-expression-xml04" /><![CDATA[
ns-uri=""> ]]><co id="xpath-expression-xml05-co" linkends="xpath-expression-xml05" /><![CDATA[
<map></map> ]]><co id="xpath-expression-xml06-co" linkends="xpath-expression-xml06" /><![CDATA[
</int-xml:xpath-expression>]]></programlisting>
<para>
<calloutlist>
<callout arearefs="xpath-expression-xml01-co" id="xpath-expression-xml01">
<para>
Defines an XPath xpression.
<emphasis>Required</emphasis>.
</para>
</callout>
<callout arearefs="xpath-expression-xml02-co" id="xpath-expression-xml02">
<para>
The Identifier of the underlying bean definition. Will be an instance of
<classname>org.springframework.xml.xpath.XPathExpression</classname>
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-expression-xml03-co" id="xpath-expression-xml03">
<para>
Reference to a map containing namespaces. The key of the map
defines the namespace prefix and the value of the map sets the
namespace URI. It is not valid to specify both this attribute
and the <code>map</code> sub element, or setting the
<code>ns-prefix</code> and <code>ns-uri</code> attribute.
<emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="xpath-expression-xml04-co" id="xpath-expression-xml04">
<para>
Allows you to set the namspace prefix directly as and attribute
on the XPath expression element. If you set <code>ns-prefix</code>,
you must also set the <code>ns-uri</code> attribute.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-expression-xml05-co" id="xpath-expression-xml05">
<para>
Allows you to set the namspace URI directly as an attribute
on the XPath expression element. If you set <code>ns-uri</code>,
you must also set the <code>ns-prefix</code> attribute.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-expression-xml06-co" id="xpath-expression-xml06">
<para>
Defines a map containing namespaces. Only one map child element
is allowed. The key of the map defines the namespace prefix
and the value of the map sets the namespace URI.
</para>
<para>
It is not valid to specify both this sub-element
and the <code>map</code> attribute, or setting the
<code>ns-prefix</code> and <code>ns-uri</code> attributes.
<emphasis>Optional</emphasis>.
</para>
</callout>
</calloutlist>
</para>
<section>
<title>Providing Namespaces (Optional) to XPath Expressions</title>
<para>
For the XPath Expression Element, namespace information can be optionally
provided as configuration parameters. As such, namespaces can be defined
using one of the following 3 choices:
</para>
<itemizedlist>
<listitem>Reference a map using the <code>namespace-map</code> attribute</listitem>
<listitem>Provide a map of namespaces using the <code>map</code> sub-element</listitem>
<listitem>Specifying the <code>ns-prefix</code> and the <code>ns-uri</code> attribute</listitem>
</itemizedlist>
<para>
All three options are mutially exlusive. Only one option can be set.
</para>
<para>
Below, please find several different usage examples on how to use XPath
expressions using the XML namespace support including the various option for
setting the XML namespaces as discussed above.
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-filter id="filterReferencingXPathExpression"
xpath-expression-ref="refToXpathExpression"/>
<int-xml:xpath-expression id="refToXpathExpression" expression="/name"/>
<int-xml:xpath-filter id="filterWithoutNamespace">
<int-xml:xpath-expression expression="/name"/>
</int-xml:xpath-filter>
<int-xml:xpath-filter id="filterWithOneNamespace">
<int-xml:xpath-expression expression="/ns1:name"
ns-prefix="ns1" ns-uri="www.example.org"/>
</int-xml:xpath-filter>
<int-xml:xpath-filter id="filterWithTwoNamespaces">
<int-xml:xpath-expression expression="/ns1:name/ns2:type">
<map>
<entry key="ns1" value="www.example.org/one"/>
<entry key="ns2" value="www.example.org/two"/>
</map>
</int-xml:xpath-expression>
</int-xml:xpath-filter>
<int-xml:xpath-filter id="filterWithNamespaceMapReference">
<int-xml:xpath-expression expression="/ns1:name/ns2:type"
namespace-map="defaultNamespaces"/>
</int-xml:xpath-filter>
<util:map id="defaultNamespaces">
<util:entry key="ns1" value="www.example.org/one"/>
<util:entry key="ns2" value="www.example.org/two"/>
</util:map>]]></programlisting>
</section>
<section>
<title>Using XPath Expressions with Default Namespaces</title>
<para>
When working with default nanmespaces, you may run into situations that
behave differently than originally expected. Let's assume we have the
following XML document:
</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<order>
<orderItem>
<isbn>0321200683</isbn>
<quantity>2</quantity>
</orderItem>
<orderItem>
<isbn>1590596439</isbn>
<quantity>1</quantity>
</orderItem>
</order>]]></programlisting>
<para>
This document is not declaring any namespace. Therefore, applying
the following XPath Expression will work as expected:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-expression expression="/order/orderItem" />]]></programlisting>
<para>
You might expect that the same expression will also work for the following
XML file. It looks exactly the same as the previous example but in addition
it also declares a default namespace:
</para>
<para><emphasis>http://www.example.org/orders</emphasis></para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<order xmlns="http://www.example.org/orders">
<orderItem>
<isbn>0321200683</isbn>
<quantity>2</quantity>
</orderItem>
<orderItem>
<isbn>1590596439</isbn>
<quantity>1</quantity>
</orderItem>
</order>]]></programlisting>
<para>
However, the XPath Expression used previously will fail in this case.
</para>
<para>
In order to solve this issue, you must provide a namespace prefix and
a namespace URI using either the <emphasis>ns-prefix</emphasis>
and <emphasis>ns-uri</emphasis> attibute or by providing a
<emphasis>namespace-map</emphasis> attribute instead. The namespace
URI must match the namespace declared in your XML document, which in
this example is <emphasis>http://www.example.org/orders</emphasis>.
</para>
<para>
The namespace prefix, however, can be arbitrarily chosen. In fact, just
providing an empty String will actually work (Null is not allowed). In the
case of a namespace prefix consisting of an empty String, your Xpath
Expression will use a colon (":") to indicate the default namespace.
If you leave the colon off, the XPath expression will not match. The following
XPath Expression will match agains the XML document above:
</para>
<programlisting language="xml"><![CDATA[<si-xml:xpath-expression expression="/:order/:orderItem"
ns-prefix="" ns-uri="http://www.example.org/prodcuts"/>]]></programlisting>
<para>
Of course you can also provide any other arbitrarily chosen namespace prefix.
The following XPath expression using the <emphasis>myorder</emphasis>
namespace prefix will match also:
</para>
<programlisting language="xml"><![CDATA[<si-xml:xpath-expression expression="/myorder:order/myorder:orderItem"
ns-prefix="myorder" ns-uri="http://www.example.org/prodcuts"/>]]></programlisting>
<para>
It is important to remember that the namespace URI is the really important
piece of information to declare, not the prefix itself. The
<ulink url="http://jaxen.codehaus.org/faq.html">Jaxen FAQ</ulink>
summarizes the point very well:
</para>
<para>
<quote>
In XPath 1.0, all unprefixed names are unqualified. There is no
requirement that the prefixes used in the XPath expression are
the same as the prefixes used in the document being queried.
Only the namespace URIs need to match, not the prefixes.
</quote>
</para>
</section>
</section>
</section>
<section id="xml-transformation">
<title>Transforming XML Payloads</title>
<section id="xml-transformation-beans">
<title>Configuring Transformers as Beans</title>
<para>
This section will explain the workings of the following transformers
and how to configure them as <emphasis>beans</emphasis>:
</para>
<itemizedlist>
<listitem>
<classname><link linkend="xml-unmarshalling-transformer">UnmarshallingTransformer</link></classname>
</listitem>
<listitem>
<classname><link linkend="xml-marshalling-transformer">MarshallingTransformer</link></classname>
</listitem>
<listitem>
<classname><link linkend="xml-xslt-payload-transformers">XsltPayloadTransformer</link></classname>
</listitem>
</itemizedlist>
<para>
All of the provided XML transformers extend
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/transformer/AbstractTransformer.html">AbstractTransformer</ulink></classname>
or <classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/transformer/AbstractPayloadTransformer.html">AbstractPayloadTransformer</ulink></classname>
and therefore implement
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/transformer/Transformer.html">Transformer</ulink></interfacename>.
When configuring XML transformers as beans in Spring Integration,
you would normally configure the <emphasis>Transformer</emphasis>
in conjunction with either a
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/transformer/MessageTransformingChannelInterceptor.html">MessageTransformingChannelInterceptor</ulink></classname>
or a <classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/transformer/MessageTransformingHandler.html">MessageTransformingHandler</ulink></classname>.
This allows the transformer to be used as either an interceptor,
which transforms the message as it is sent or received to the
<emphasis>Channel</emphasis>, or as an <emphasis>Endpoint</emphasis>.
Finally, the namespace support will be discussed, which allows for
the simple configuration of the transformers as elements in XML.
</para>
<section id="xml-unmarshalling-transformer">
<title>UnmarshallingTransformer</title>
<para>
An <classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/UnmarshallingTransformer.html">UnmarshallingTransformer</ulink></classname>
allows an XML <interfacename>Source</interfacename> to be
unmarshalled using implementations of the
<ulink url="http://static.springsource.org/spring-ws/site/reference/html/oxm.html">Spring OXM</ulink>
<interfacename>Unmarshaller</interfacename>. Spring's Object/XML Mapping
support provides several implementations supporting marshalling
and unmarshalling using
<ulink url="http://en.wikipedia.org/wiki/Java_Architecture_for_XML_Binding">JAXB</ulink>,
<ulink url="http://www.castor.org/">Castor</ulink> and
<ulink url="http://jibx.sourceforge.net/">JiBX</ulink> amongst others.
The unmarshaller requires an instance of <interfacename>Source</interfacename>.
If the message payload is not an instance of <interfacename>Source</interfacename>,
conversion will be attempted. Currently <classname>String</classname>,
<classname>File</classname> and <interfacename>org.w3c.dom.Document</interfacename>
payloads are supported. Custom conversion to a <interfacename>Source</interfacename>
is also supported by injecting an implementation of a
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/source/SourceFactory.html">SourceFactory</ulink></interfacename>.
</para>
<note>
If a <interfacename>SourceFactory</interfacename> is not set
explicitly, the property on the <classname>UnmarshallingTransformer</classname>
will by default be set to a
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/source/DomSourceFactory.html">DomSourceFactory</ulink></classname>.
</note>
<programlisting language="xml"><![CDATA[<bean id="unmarshallingTransformer" class="o.s.i.xml.transformer.UnmarshallingTransformer">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="org.example" />
</bean>
</constructor-arg>
</bean>]]></programlisting>
</section>
<section id="xml-marshalling-transformer">
<title>MarshallingTransformer</title>
<para>
The <classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/MarshallingTransformer.html">MarshallingTransformer</ulink></classname>
allows an object graph to be converted into XML using a Spring OXM
<interfacename>Marshaller</interfacename>. By default the
<classname>MarshallingTransformer</classname> will return a
<classname>DomResult</classname>. However, the type of result can be
controlled by configuring an alternative <interfacename>ResultFactory</interfacename>
such as <classname>StringResultFactory</classname>. In many cases it
will be more convenient to transform the payload into an alternative
XML format. To achieve this, configure a <interfacename>ResultTransformer</interfacename>.
Two implementations are provided, one which converts to <classname>String</classname>
and another which converts to <interfacename>Document</interfacename>.
</para>
<programlisting language="xml"><![CDATA[<bean id="marshallingTransformer" class="o.s.i.xml.transformer.MarshallingTransformer">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="org.example"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
</constructor-arg>
</bean>]]></programlisting>
<para>
By default, the <classname>MarshallingTransformer</classname> will pass the payload Object
to the <interfacename>Marshaller</interfacename>, but if its boolean <code>extractPayload</code> property
is set to <code>false</code>, the entire <interfacename>Message</interfacename> instance will be passed
to the <interfacename>Marshaller</interfacename> instead. That may be useful for certain custom
implementations of the <interfacename>Marshaller</interfacename> interface, but typically the
payload is the appropriate source Object for marshalling when delegating to any of the various
out-of-the-box <interfacename>Marshaller</interfacename> implementations.
</para>
</section>
<section id="xml-xslt-payload-transformers">
<title>XsltPayloadTransformer</title>
<para>
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/XsltPayloadTransformer.html">XsltPayloadTransformer</ulink></classname>
transforms XML payloads using <ulink url="http://en.wikipedia.org/wiki/XSL_Transformations">Extensible Stylesheet Language Transformations</ulink> (XSLT).
The transformer's constructor requires an instance of either
<interfacename><ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/core/io/Resource.html">Resource</ulink></interfacename>
or <interfacename><ulink url="http://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Templates.html">Templates</ulink></interfacename>
to be passed in. Passing in a <interfacename>Templates</interfacename>
instance allows for greater configuration of the <interfacename>TransformerFactory</interfacename>
used to create the template instance.
</para>
<para>
As with the <classname><link linkend="xml-unmarshalling-transformer">UnmarshallingTransformer</link></classname>,
the <classname>XsltPayloadTransformer</classname> will do the actual
XSLT transformation using instances of <interfacename>Source</interfacename>.
Therefore, if the message payload is not an instance of <interfacename>Source</interfacename>,
conversion will be attempted. <classname>String</classname> and
<interfacename>Document</interfacename> payloads are supported directly.
</para>
<para>
Custom conversion to a <interfacename>Source</interfacename> is also
supported by injecting an implementation of a
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/source/SourceFactory.html">SourceFactory</ulink></interfacename>.
</para>
<note>
If a <interfacename>SourceFactory</interfacename> is not set
explicitly, the property on the <classname>XsltPayloadTransformer</classname>
will by default be set to a
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/source/DomSourceFactory.html">DomSourceFactory</ulink></classname>.
</note>
<para>
By default, the <classname>XsltPayloadTransformer</classname> will create a message
with a
<interfacename><ulink url="http://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Result.html">Result</ulink></interfacename>
payload, similar to the <classname>XmlPayloadMarshallingTransformer</classname>.
This can be customised by providing a
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/result/ResultFactory.html">ResultFactory</ulink></interfacename>
and/or a <interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/ResultTransformer.html">ResultTransformer</ulink></interfacename>.
</para>
<programlisting language="xml"><![CDATA[<bean id="xsltPayloadTransformer" class="o.s.i.xml.transformer.XsltPayloadTransformer">
<constructor-arg value="classpath:org/example/xsl/transform.xsl"/>
<constructor-arg>
<bean class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
</constructor-arg>
</bean>]]></programlisting>
<para>
Starting with Spring Integration 3.0, you can now specify the transformer factory class name using
a constructor argument. This is configured using the <code>transformer-factory-class</code>
attribute when using the namespace.
</para>
</section>
<section id="xml-using-result-transformers">
<title>ResultTransformers</title>
<para>
Both the <classname>MarshallingTransformer</classname> and the
<classname>XsltPayloadTransformer</classname> allow you to specify a
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/ResultTransformer.html">ResultTransformer</ulink></interfacename>.
Thus, if the Marshalling or XSLT transformation returns a <interfacename><ulink url="http://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Result.html">Result</ulink></interfacename>,
than you have the option to also use a <interfacename>ResultTransformer</interfacename>
to transform the <interfacename>Result</interfacename> into another
format. Spring Integration provides 2 concrete
<interfacename>ResultTransformer</interfacename> implementations:
</para>
<itemizedlist>
<listitem><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/ResultToDocumentTransformer.html">ResultToDocumentTransformer</ulink></listitem>
<listitem><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/ResultToStringTransformer.html">ResultToStringTransformer</ulink></listitem>
</itemizedlist>
<para><emphasis>Using ResultTransformers with the MarshallingTransformer</emphasis></para>
<para>
By default, the <emphasis>MarshallingTransformer</emphasis> will always
return a <interfacename><ulink url="http://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Result.html">Result</ulink></interfacename>.
By specifying a <interfacename>ResultTransformer</interfacename>, you can customize the
type of payload returned.
</para>
<para><emphasis>Using ResultTransformers with the XsltPayloadTransformer</emphasis></para>
<para>
The behavior is slighly more complex for the <emphasis>XsltPayloadTransformer</emphasis>.
By default, if the input payload is an instance of <classname>String</classname>
or <interfacename><ulink url="http://docs.oracle.com/javase/6/docs/api/org/w3c/dom/Document.html">Document</ulink></interfacename>
the <emphasis>resultTransformer</emphasis> property is ignored.
</para>
<para>
However, if the input payload is a
<interfacename><ulink url="http://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Source.html">Source</ulink></interfacename>
or any other type, then the <emphasis>resultTransformer</emphasis> property is
applied. Additionally, you can set the property <emphasis>alwaysUseResultFactory</emphasis>
to <code>true</code>, which will also cause the specified <emphasis>resultTransformer</emphasis> to
being used.
</para>
<para>
For more information and examples, please see <xref linkend="xml-using-result-transformers-namespace"/>
</para>
</section>
</section>
<section id="xml-transformer-namespace">
<title>Namespace Support for XML Transformers</title>
<para>
Namespace support for all XML transformers is provided in the Spring Integration XML namespace,
a template for which can be seen below. The namespace support for transformers creates an instance of either
<classname>EventDrivenConsumer</classname> or <classname>PollingConsumer</classname>
according to the type of the provided input channel. The namespace support is designed
to reduce the amount of XML configuration by allowing the creation of an endpoint and transformer
using one element.
</para>
<para><emphasis>UnmarshallingTransformer</emphasis></para>
<para>
The namespace support for the <classname>UnmarshallingTransformer</classname>
is shown below. Since the namespace is now creating an endpoint instance
rather than a transformer, a poller can also be nested within the
element to control the polling of the input channel.
</para>
<programlisting language="xml"><![CDATA[<int-xml:unmarshalling-transformer id="defaultUnmarshaller"
input-channel="input" output-channel="output"
unmarshaller="unmarshaller"/>
<int-xml:unmarshalling-transformer id="unmarshallerWithPoller"
input-channel="input" output-channel="output"
unmarshaller="unmarshaller">
<int:poller fixed-rate="2000"/>
<int-xml:unmarshalling-transformer/>]]></programlisting>
<para><emphasis>MarshallingTransformer</emphasis></para>
<para>
The namespace support for the marshalling transformer requires an
<code>input-channel</code>, <code>output-channel</code> and a reference
to a <code>marshaller</code>. The optional <code>result-type</code>
attribute can be used to control the type of result created. Valid values
are <code>StringResult</code> or <code>DomResult</code> (the default).
</para>
<programlisting language="xml"><![CDATA[<int-xml:marshalling-transformer
input-channel="marshallingTransformerStringResultFactory"
output-channel="output"
marshaller="marshaller"
result-type="StringResult" />
<int-xml:marshalling-transformer
input-channel="marshallingTransformerWithResultTransformer"
output-channel="output"
marshaller="marshaller"
result-transformer="resultTransformer" />
<bean id="resultTransformer" class="o.s.i.xml.transformer.ResultToStringTransformer"/>]]></programlisting>
<para>
Where the provided result types are not sufficient, a reference to a custom
implementation of <interfacename>ResultFactory</interfacename> can be
provided as an alternative to setting the <code>result-type</code>
attribute, using the <code>result-factory</code> attribute. The attributes
<emphasis>result-type</emphasis> and <emphasis>result-factory</emphasis>
are mutually exclusive.
</para>
<note>
Internally, the result types <code>StringResult</code> and <code>DomResult</code>
are represented by the <interfacename>ResultFactory</interfacename>s
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/result/StringResultFactory.html">StringResultFactory</ulink></classname>
and <classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/result/DomResultFactory.html">DomResultFactory</ulink></classname>
respectively.
</note>
<para><emphasis>XsltPayloadTransformer</emphasis></para>
<para>
Namespace support for the <classname>XsltPayloadTransformer</classname>
allows you to either pass in a <interfacename>Resource</interfacename>,
in order to create the
<interfacename><ulink url="http://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Templates.html">Templates</ulink></interfacename>
instance,
or alternatively, you can pass in a precreated <interfacename>Templates</interfacename>
instance as a reference. In common with the marshalling transformer,
the type of the result output can be controlled by specifying either
the <code>result-factory</code> or <code>result-type</code> attribute.
A <code>result-transfomer</code> attribute can also be used to reference
an implementation of <interfacename>ResultTransfomer</interfacename>
where conversion of the result is required before sending.
</para>
<important>
If you specify the <code>result-factory</code> or the <code>result-type</code>
attribute, then the <code>alwaysUseResultFactory</code> property on
the underlying
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/XsltPayloadTransformer.html">XsltPayloadTransformer</ulink></classname>
will be set to <code>true</code> by the
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/config/XsltPayloadTransformerParser.html">XsltPayloadTransformerParser</ulink></classname>.
</important>
<programlisting language="xml"><![CDATA[<int-xml:xslt-transformer id="xsltTransformerWithResource"
input-channel="withResourceIn" output-channel="output"
xsl-resource="org/springframework/integration/xml/config/test.xsl"/>
<int-xml:xslt-transformer id="xsltTransformerWithTemplatesAndResultTransformer"
input-channel="withTemplatesAndResultTransformerIn" output-channel="output"
xsl-templates="templates"
result-transformer="resultTransformer"/>]]></programlisting>
<para>
Often you may need to have access to Message data, such as the
Message Headers, in order to assist with transformation. For example,
you may need to get access to certain Message Headers and pass them
on as parameters to a transformer (e.g., transformer.setParameter(..)).
Spring Integration provides two convenient ways to accomplish this, as
illustrated in following example:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xslt-transformer id="paramHeadersCombo"
input-channel="paramHeadersComboChannel" output-channel="output"
xsl-resource="classpath:transformer.xslt"
xslt-param-headers="testP*, *foo, bar, baz">
<int-xml:xslt-param name="helloParameter" value="hello"/>
<int-xml:xslt-param name="firstName" expression="headers.fname"/>
</int-xml:xslt-transformer>]]></programlisting>
<para>
If message header names match 1:1 to parameter names, you can simply use
<code>xslt-param-headers</code> attribute. There you can also use wildcards
for simple pattern matching, which supports the following simple pattern
styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy".
</para>
<para>
You can also configure individual Xslt parameters via the <emphasis>&lt;xslt-param/&gt;</emphasis>
sub element. There you can use either the <code>expression</code> or
<code>value</code> attribute.
The <code>expression</code> attribute should be any valid SpEL expression
with Message being the root object of the expression evaluation context.
The <code>value</code> attribute, just like any <code>value</code>
in Spring beans, allows you to specify simple scalar values. You can
also use property placeholders (e.g., ${some.value}). So as you can
see, with the <code>expression</code> and <code>value</code> attribute,
Xslt parameters could now be mapped to any accessible part of the Message
as well as any literal value.
</para>
<para>
Starting with Spring Integration 3.0, you can now specify the transformer factory class name using
the <code>transformer-factory-class</code> attribute.
</para>
</section>
<section id="xml-using-result-transformers-namespace">
<title>Namespace Configuration and ResultTransformers</title>
<para>
The usage of <interfacename>ResultTransformers</interfacename> was
previously introduced in <xref linkend="xml-using-result-transformers"/>.
The following example illustrates several special use-cases using XML
namespace configuration. First, we define the
<interfacename>ResultTransformer</interfacename>:
</para>
<programlisting language="xml"><![CDATA[<beans:bean id="resultToDoc" class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>]]></programlisting>
<para>
This <interfacename>ResultTransformer</interfacename> will accept either
a <classname>StringResult</classname> or a <classname>DOMResult</classname>
as input and converts the input into a <classname>Document</classname>.
</para>
<para>
Now, let's declare the transformer:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"/>]]></programlisting>
<para>
If the incoming message's payload is of type <interfacename>Source</interfacename>,
then as first step the <interfacename>Result</interfacename> is determined
using the <interfacename>ResultFactory</interfacename>. As we did not
specify a <interfacename>ResultFactory</interfacename>, the default
<classname>DomResultFactory</classname> is used, meaning that the
transformation will yield a <classname>DomResult</classname>.
</para>
<para>
However, as we specified a <emphasis>ResultTransformer</emphasis>, it
will be used and the resulting Message payload will be of type
<interfacename>Document</interfacename>.
</para>
<important>
If the incoming message's payload is of type <classname>String</classname>,
the payload after the Xslt transformation will be a String. Similarly,
if the incoming message's payload is of type <interfacename>Document</interfacename>,
the payload after the Xslt transformation will be a
<interfacename>Document</interfacename>. The specified
<emphasis>ResultTransformer</emphasis> will be ignored with
<classname>String</classname> or <interfacename>Document</interfacename>
payloads.
</important>
<para>
If the message payload is neither a <interfacename>Source</interfacename>,
<classname>String</classname> or <interfacename>Document</interfacename>,
as a fallback option, it is attempted to create a
<interfacename>Source</interfacename> using the default
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/source/SourceFactory.html">SourceFactory</ulink></interfacename>.
As we did not specify a <interfacename>SourceFactory</interfacename>
explicitly using the <emphasis>source-factory</emphasis> attribute,
the default <classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/source/DomSourceFactory.html">DomSourceFactory</ulink></classname>
is used. If successful, the XSLT transformation is executed as if
the payload was of type <interfacename>Source</interfacename>, which
we described in the previous paragraphs.
</para>
<note>
The <classname>DomSourceFactory</classname> supports the creation of
a <classname>DOMSource</classname> from a either
<interfacename>Document</interfacename>, <classname>File</classname>
or <classname>String</classname> payloads.
</note>
<para>
The next transformer declaration adds a <emphasis>result-type</emphasis>
attribute using <code>StringResult</code> as its value. First, the
<emphasis>result-type</emphasis> is internally represented by the
<classname>StringResultFactory</classname>. Thus, you could have also
added a reference to a <classname>StringResultFactory</classname>, using
the <emphasis>result-factory</emphasis> attribute, which would haven
been the same.
</para>
<programlisting language="xml"><![CDATA[<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"
result-type="StringResult"/>]]></programlisting>
<para>
Because we are using a <classname>ResultFactory</classname>, the
<emphasis>alwaysUseResultFactory</emphasis> property of the
<classname>XsltPayloadTransformer</classname> class will be implicitly
set to <code>true</code>. Consequently, the referenced
<classname>ResultToDocumentTransformer</classname> will be used.
</para>
<para>
Therefore, if you transform a payload of type
<classname>String</classname>, the resulting payload will be of type
<classname><ulink url="http://docs.oracle.com/javase/6/docs/api/org/w3c/dom/Document.html">Document</ulink></classname>.
</para>
<para><emphasis>XsltPayloadTransformer and &lt;xsl:output method="text"/&gt;</emphasis></para>
<para><code>&lt;xsl:output method="text"/&gt;</code> tells the XSLT
template to only produce text content from the input source.
In this particuliar case there is no reason to have a
<classname>DomResult</classname>. Therefore, the
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/xml/transformer/XsltPayloadTransformer.html">XsltPayloadTransformer</ulink></classname>
defaults to <classname>StringResult</classname> if the
<ulink url="http://docs.oracle.com/javase/7/docs/api/javax/xml/transform/Transformer.html#getOutputProperties()">output property</ulink>
called <code>method</code> of the underlying
<classname>javax.xml.transform.Transformer</classname> returns <code>"text"</code>.
This coercion is performed independent from the inbound payload type. Keep
in mind that this <quote>smart</quote> behavior is only available, if the
<code>result-type</code> or <code>result-factory</code> attributes
aren't provided for the respective <code>&lt;int-xml:xslt-transformer&gt;</code>
component.
</para>
</section>
</section>
<section id="xml-xpath-transformer">
<title>Transforming XML Messages Using XPath</title>
<para>
When it comes to message transformation XPath is a great way to transform Messages that have XML
payloads by defining XPath transformers via &lt;xpath-transformer/&gt; element.
</para>
<para>
<emphasis>Simple XPath transformation</emphasis>
</para>
<para>
Let's look at the following transformer configuration:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-transformer input-channel="inputChannel" output-channel="outputChannel"
xpath-expression="/person/@name" />]]></programlisting>
<para>
. . . and Message
</para>
<programlisting language="java"><![CDATA[Message<?> message =
MessageBuilder.withPayload("<person name='John Doe' age='42' married='true'/>").build();]]></programlisting>
<para>
After sending this message to the 'inputChannel' the XPath transformer configured above will transform
this XML Message to a simple Message with payload of 'John Doe' all based on
the simple XPath Expression specified in the <code>xpath-expression</code> attribute.
</para>
<para>
XPath also has the capability to perform simple conversion of extracted elements
to a desired type. Valid return types are defined in <classname>javax.xml.xpath.XPathConstants</classname> and follows
the conversion rules specified by the <interfacename>javax.xml.xpath.XPath</interfacename> interface.
</para>
<para>
The following constants are defined by the <classname>XPathConstants</classname> class: <emphasis>BOOLEAN, DOM_OBJECT_MODEL, NODE, NODESET, NUMBER, STRING</emphasis>
</para>
<para>
You can configure the desired type by simply using the <code>evaluation-type</code>
attribute of the <code>&lt;xpath-transformer/&gt;</code> element.
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-transformer input-channel="numberInput" xpath-expression="/person/@age"
evaluation-type="NUMBER_RESULT" output-channel="output"/>
<int-xml:xpath-transformer input-channel="booleanInput"
xpath-expression="/person/@married = 'true'"
evaluation-type="BOOLEAN_RESULT" output-channel="output"/>
]]></programlisting>
<para>
<emphasis>Node Mappers</emphasis>
</para>
<para>
If you need to provide custom mapping for the node extracted by the XPath expression simply provide a reference to the
implementation of the <classname>org.springframework.xml.xpath.NodeMapper</classname> - an interface used by
<classname>XPathOperations</classname> implementations for mapping Node objects on a per-node basis. To provide a
reference to a <classname>NodeMapper</classname> simply use <code>node-mapper</code> attribute:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-transformer input-channel="nodeMapperInput" xpath-expression="/person/@age"
node-mapper="testNodeMapper" output-channel="output"/>]]></programlisting>
<para>
. . . and Sample NodeMapper implementation:
</para>
<programlisting language="java"><![CDATA[class TestNodeMapper implements NodeMapper {
public Object mapNode(Node node, int nodeNum) throws DOMException {
return node.getTextContent() + "-mapped";
}
}]]></programlisting>
<para>
<emphasis>XML Payload Converter</emphasis>
</para>
<para>
You can also use an implementation of the <classname>org.springframework.integration.xml.XmlPayloadConverter</classname> to
provide more granular transformation:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-transformer input-channel="customConverterInput"
output-channel="output" xpath-expression="/test/@type"
converter="testXmlPayloadConverter" />
]]></programlisting>
<para>
. . . and Sample XmlPayloadConverter implementation:
</para>
<programlisting language="java"><![CDATA[class TestXmlPayloadConverter implements XmlPayloadConverter {
public Source convertToSource(Object object) {
throw new UnsupportedOperationException();
}
//
public Node convertToNode(Object object) {
try {
return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new InputSource(new StringReader("<test type='custom'/>")));
}
catch (Exception e) {
throw new IllegalStateException(e);
}
}
//
public Document convertToDocument(Object object) {
throw new UnsupportedOperationException();
}
}]]></programlisting>
<para>The DefaultXmlPayloadConverter is used if this reference is not provided, and it
should be sufficient in most cases since it can convert from Node, Document, Source,
File, and String typed payloads. If you need to extend beyond the capabilities of
that default implementation, then an upstream Transformer is probably a better option
than providing a reference to a custom implementation of this strategy here.</para>
</section><section id="xml-xpath-splitting">
<title>Splitting XML Messages</title>
<para>
<classname>XPathMessageSplitter</classname> supports messages with either
<classname>String</classname> or <interfacename>Document</interfacename> payloads.
The splitter uses the provided XPath expression to split the payload into a number of
nodes. By default this will result in each <interfacename>Node</interfacename> instance
becoming the payload of a new message. Where it is preferred that each message be a Document
the <methodname>createDocuments</methodname> flag can be set. Where a <classname>String</classname> payload is passed
in the payload will be converted then split before being converted back to a number of String
messages. The XPath splitter implements <interfacename>MessageHandler</interfacename> and should
therefore be configured in conjunction with an appropriate endpoint (see the namespace support below
for a simpler configuration alternative).
</para>
<programlisting language="xml"><![CDATA[<bean id="splittingEndpoint"
class="org.springframework.integration.endpoint.EventDrivenConsumer">
<constructor-arg ref="orderChannel" />
<constructor-arg>
<bean class="org.springframework.integration.xml.splitter.XPathMessageSplitter">
<constructor-arg value="/order/items" />
<property name="documentBuilder" ref="customisedDocumentBuilder" />
<property name="outputChannel" ref="orderItemsChannel" />
</bean>
</constructor-arg>
</bean>]]></programlisting>
<para>
XPath splitter namespace support allows the creation of a Message Endpoint with an input channel and output channel.
</para>
<programlisting language="xml"><![CDATA[<!-- Split the order into items creating a new message for each item node -->
<int-xml:xpath-splitter id="orderItemSplitter"
input-channel="orderChannel"
output-channel="orderItemsChannel">
<int-xml:xpath-expression expression="/order/items"/>
</int-xml:xpath-splitter>
<!-- Split the order into items creating a new document for each item-->
<int-xml:xpath-splitter id="orderItemDocumentSplitter"
input-channel="orderChannel"
output-channel="orderItemsChannel"
create-documents="true">
<int-xml:xpath-expression expression="/order/items"/>
<int:poller fixed-rate="2000"/>
</int-xml:xpath-splitter>]]></programlisting>
</section>
<section id="xml-xpath-routing">
<title id="xml-xpath-routing.title">Routing XML Messages Using XPath</title>
<para>
Similar to SpEL-based routers, Spring Integration provides support for routing messages based on XPath expressions,
allowing you to create a Message Endpoint with an input channel but no output channel. Instead, one or more output
channels are determined dynamically.
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-router id="orderTypeRouter" input-channel="orderChannel">
<si-xml:xpath-expression expression="/order/type"/>
</int-xml:xpath-router>]]></programlisting>
<note>
For an overview of attributes that are common among Routers, please see chapter:
<emphasis><xref linkend='router-common-parameters' endterm="router-common-parameters.title"/></emphasis>
</note>
<para>
Internally XPath expressions will be evaluated as <emphasis>NODESET</emphasis>
type and converted to a <classname>List&lt;String&gt;</classname> representing
channel names. Typically such a list will contain a single channel name.
However, based on the results of an XPath Expression, the XPath router can
also take on the characteristics of a <emphasis>Recipient List Router</emphasis>
if the XPath Expression returns more then one value. In that case, the
<classname>List&lt;String&gt;</classname> will contain more then one
channel name and consequently Messages will be sent to all channels in the list.
</para>
<para>
Thus, assuming that the XML file passed to the router configured below
contains many <code>responder</code> sub-elements representing channel names,
the message will be sent to all of those channels.
</para>
<programlisting language="xml"><![CDATA[<!-- route the order to all responders-->
<int-xml:xpath-router id="responderRouter" input-channel="orderChannel">
<int-xml:xpath-expression expression="/request/responders"/>
</int-xml:xpath-router>
]]></programlisting>
<para>
If the returned values do not represent the channel names directly, additional
mapping parameters can be specified, in order to map those returned values to actual
channel names. For example if the <code>/request/responders</code> expression
results in two values <code>responderA</code> and <code>responderB</code> but
you don't want to couple the responder names to channel names, you may provide
additional mapping configuration such as the following:
</para>
<programlisting language="xml"><![CDATA[<!-- route the order to all responders-->
<int-xml:xpath-router id="responderRouter" input-channel="orderChannel">
<int-xml:xpath-expression expression="/request/responders"/>
<int-xml:mapping value="responderA" channel="channelA"/>
<int-xml:mapping value="responderB" channel="channelB"/>
</int-xml:xpath-router>
]]></programlisting>
<para>
As already mentioned, the default evaluation type for XPath expressions is
<emphasis>NODESET</emphasis>, which is converted to a
<code>List&lt;String&gt;</code> of channel names, therefore handling
single channel scenarios as well as multiple ones.
</para>
<para>
Nonetheless, certain XPath expressions may evaluate as String type from the
very beginning. Take for example the following XPath Expression:
</para>
<programlisting language="xml"><![CDATA[name(./node())]]></programlisting>
<para>
This expression will return the name of the root node. It will resulting
in an exception, if the default evaluation type <emphasis>NODESET</emphasis>
is being used.
</para>
<para>
For these scenarious, you may use the <code>evaluate-as-string</code> attribute,
which will allow you to manage the evaluation type. It is <code>FALSE</code>
by default, however if set to <code>TRUE</code>, the String evaluation
type will be used.
</para>
<note>
<para>
To provide some background information: XPath 1.0 specifies 4 data types:
</para>
<itemizedlist>
<listitem>Node-sets</listitem>
<listitem>Strings</listitem>
<listitem>Number</listitem>
<listitem>Boolean</listitem>
</itemizedlist>
<para>
When the XPath Router evaluates expressions using the optional
<code>evaluate-as-string</code> attribute, the return value is
determined per the <code>string()</code> function as defined in the
XPath specification. This means that if the expression selects
multiple nodes, it will return the string value of the first node.
</para>
<para>
For further information, please see:
</para>
<itemizedlist>
<listitem>Specification: XML Path Language (XPath) Version 1.0: http://www.w3.org/TR/xpath/</listitem>
<listitem>XPath specification - string() function: http://www.w3.org/TR/xpath/#function-string</listitem>
</itemizedlist>
</note>
<para>
For example if we want to route based on the name of the root node, we
can use the following configuration:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-router id="xpathRouterAsString"
input-channel="xpathStringChannel"
evaluate-as-string="true">
<int-xml:xpath-expression expression="name(./node())"/>
</int-xml:xpath-router>
]]></programlisting>
<section id="xpath-routing-converter">
<title>XML Payload Converter</title>
<para>
For XPath Routers, you can also specify the Converter to use when converting
payloads prior to XPath evaluation. As such, the XPath Router supports
custom implementations of the <classname>XmlPayloadConverter</classname> strategy,
and when configuring an <code>xpath-router</code> element in XML, a reference
to such an implementation may be provided via the <code>converter</code> attribute.
</para>
<para>
If this reference is not explicitly provided, the <classname>DefaultXmlPayloadConverter</classname>
is used. It should be sufficient in most cases, since it can convert from
Node, Document, Source, File, and String typed payloads. If you need to
extend beyond the capabilities of that default implementation, then an
upstream Transformer is generally a better option in most cases, rather
than providing a reference to a custom implementation of this strategy here.
</para>
</section>
</section>
<section id="xml-xpath-header-enricher">
<title>XPath Header Enricher</title>
<para>
The XPath Header Enricher defines a Header Enricher Message Transformer
that evaluates XPath expressions against the message payload and inserts
the result of the evaluation into a messsage header.
</para>
<para>
Please see below for an overview of all available configuration parameters:
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-header-enricher default-overwrite="true" ]]><co id="xpath-header-enricher-xml01-co" linkends="xpath-header-enricher-xml01" /><![CDATA[
id="" ]]><co id="xpath-header-enricher-xml02-co" linkends="xpath-header-enricher-xml02" /><![CDATA[
input-channel="" ]]><co id="xpath-header-enricher-xml03-co" linkends="xpath-header-enricher-xml03" /><![CDATA[
output-channel="" ]]><co id="xpath-header-enricher-xml04-co" linkends="xpath-header-enricher-xml04" /><![CDATA[
should-skip-nulls="true"> ]]><co id="xpath-header-enricher-xml05-co" linkends="xpath-header-enricher-xml05" /><![CDATA[
<int:poller></int:poller> ]]><co id="xpath-header-enricher-xml06-co" linkends="xpath-header-enricher-xml06" /><![CDATA[
<int-xml:header name="" ]]><co id="xpath-header-enricher-xml07-co" linkends="xpath-header-enricher-xml07" /><![CDATA[
evaluation-type="STRING_RESULT" ]]><co id="xpath-header-enricher-xml08-co" linkends="xpath-header-enricher-xml08" /><![CDATA[
overwrite="true" ]]><co id="xpath-header-enricher-xml09-co" linkends="xpath-header-enricher-xml09" /><![CDATA[
xpath-expression="" ]]><co id="xpath-header-enricher-xml10-co" linkends="xpath-header-enricher-xml10" /><![CDATA[
xpath-expression-ref=""/> ]]><co id="xpath-header-enricher-xml11-co" linkends="xpath-header-enricher-xml11" /><![CDATA[
</int-xml:xpath-header-enricher>]]>
</programlisting>
<para>
<calloutlist>
<callout arearefs="xpath-header-enricher-xml01-co" id="xpath-header-enricher-xml01">
<para>
Specify the default boolean value for whether to overwrite existing
header values. This will only take effect for sub-elements that
do not provide their own 'overwrite' attribute. If the 'default-
overwrite' attribute is not provided, then the specified header
values will NOT overwrite any existing ones with the same header names.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-header-enricher-xml02-co" id="xpath-header-enricher-xml02">
<para>
Id for the underlying bean definition.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-header-enricher-xml03-co" id="xpath-header-enricher-xml03">
<para>The receiving Message channel of this endpoint. <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="xpath-header-enricher-xml04-co" id="xpath-header-enricher-xml04">
Channel to which enriched messages shall be send to. <emphasis>Optional</emphasis>.
</callout>
<callout arearefs="xpath-header-enricher-xml05-co" id="xpath-header-enricher-xml05">
<para>
Specify whether null values, such as might be returned from
an expression evaluation, should be skipped. The default value
is true. Set this to false if a null value should trigger removal of the
corresponding header instead.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-header-enricher-xml06-co" id="xpath-header-enricher-xml06">
<para>
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-header-enricher-xml07-co" id="xpath-header-enricher-xml07">
<para>
The name of the header to be enriched.
<emphasis>Mandatory</emphasis>.
</para>
</callout>
<callout arearefs="xpath-header-enricher-xml08-co" id="xpath-header-enricher-xml08">
<para>
The result type expected from the XPath evaluation. This will be the type of the header value.
The following values are allowed: BOOLEAN_RESULT, STRING_RESULT, NUMBER_RESULT, NODE_RESULT and NODE_LIST_RESULT.
Defaults internally to <code>XPathEvaluationType.STRING_RESULT</code> if not set. <emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-header-enricher-xml09-co" id="xpath-header-enricher-xml09">
<para>
Boolean value to indicate whether this header value should overwrite an existing header value for
the same name if already present on the input Message.
</para>
</callout>
<callout arearefs="xpath-header-enricher-xml10-co" id="xpath-header-enricher-xml10">
<para>
The XPath Expression as a String. Either this attribute or
<code>xpath-expression-ref</code> must be provided, but not both.
</para>
</callout>
<callout arearefs="xpath-header-enricher-xml11-co" id="xpath-header-enricher-xml11">
<para>
The XPath Expression reference. Either this attribute or
<code>xpath-expression</code> must be provided, but not both.
</para>
</callout>
</calloutlist>
</para>
</section>
<section id="xml-xpath-filter">
<title>Using the XPath Filter</title>
<para>
This component defines an XPath-based Message Filter. Under the covers this
components uses a <code>MessageFilter</code> that wraps an instance
of <code>AbstractXPathMessageSelector</code>.
</para>
<note>
Please also refer to the chapter on <link linkend='filter'>
Message Filters</link> for further details.
</note>
<para>
In order to use the XPath Filter you must as a minimum provide an XPath
Expression either by declaring the <code>xpath-expression</code> sub-element
or by referencing an XPath Expression using the <code>xpath-expression-ref</code>
attribute.
</para>
<para>
If the provided XPath expression will evaluate to a <code>boolean</code>
value, no further configuration parameters are necessary. However, if
the XPath expression will evaluate to a String, the <code>match-value</code>
attribute should be specified against which the evaluation result will
be matched.
</para>
<para>
There are three options for the <code>match-type</code>:
</para>
<itemizedlist>
<listitem>
<emphasis role="bold">exact</emphasis> - correspond to <code>equals</code> on <code>java.lang.String</code>.
The underlying implementation uses a <code>StringValueTestXPathMessageSelector</code>
</listitem>
<listitem>
<emphasis role="bold">case-insensitive</emphasis> - correspond to <code>equals-ignore-case</code> on <code>java.lang.String</code>.
The underlying implementation uses a <code>StringValueTestXPathMessageSelector</code>
</listitem>
<listitem>
<emphasis role="bold">regex</emphasis> - matches operations one <code>java.lang.String</code>.
The underlying implementation uses a <code>RegexTestXPathMessageSelector</code>
</listitem>
</itemizedlist>
<para>
When providing a 'match-type' value of 'regex', the value provided with
thos <code>match-value</code> attribute must be a valid Regular Expression.
</para>
<programlisting language="xml"><![CDATA[<int-xml:xpath-filter discard-channel="" ]]><co id="xpath-filter-xml01-co" linkends="xpath-filter-xml01" /><![CDATA[
id="" ]]><co id="xpath-filter-xml02-co" linkends="xpath-filter-xml02" /><![CDATA[
input-channel="" ]]><co id="xpath-filter-xml03-co" linkends="xpath-filter-xml03" /><![CDATA[
match-type="exact" ]]><co id="xpath-filter-xml04-co" linkends="xpath-filter-xml04" /><![CDATA[
match-value="" ]]><co id="xpath-filter-xml05-co" linkends="xpath-filter-xml05" /><![CDATA[
output-channel="" ]]><co id="xpath-filter-xml06-co" linkends="xpath-filter-xml06" /><![CDATA[
throw-exception-on-rejection="false" ]]><co id="xpath-filter-xml07-co" linkends="xpath-filter-xml07" /><![CDATA[
xpath-expression-ref=""> ]]><co id="xpath-filter-xml08-co" linkends="xpath-filter-xml08" /><![CDATA[
<int-xml:xpath-expression ... /> ]]><co id="xpath-filter-xml09-co" linkends="xpath-filter-xml09" /><![CDATA[
<int:poller ... /> ]]><co id="xpath-filter-xml10-co" linkends="xpath-filter-xml10" /><![CDATA[
</int-xml:xpath-filter>]]></programlisting>
<para>
<calloutlist>
<callout arearefs="xpath-filter-xml01-co" id="xpath-filter-xml01">
<para>
Message Channel where you want rejected messages to be sent.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-filter-xml02-co" id="xpath-filter-xml02">
<para>
Id for the underlying bean definition.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-filter-xml03-co" id="xpath-filter-xml03">
<para>The receiving Message channel of this endpoint. <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="xpath-filter-xml04-co" id="xpath-filter-xml04">
<para>
Type of match to apply between the XPath evaluation result and
the <emphasis>match-value</emphasis>.
Default is <emphasis>exact</emphasis>. <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="xpath-filter-xml05-co" id="xpath-filter-xml05">
<para>
String value to be matched against the XPath evaluation result.
If this attribute is not provided, then the XPath evaluation
MUST produce a boolean result directly.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-filter-xml06-co" id="xpath-filter-xml06">
<para>
The channel to which Messages that matched the filter criterias
shall be dispatched to. <emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-filter-xml07-co" id="xpath-filter-xml07">
<para>
By default, this property is set to <emphasis>false</emphasis>
and rejected Messages (Messages that did not match the filter
criteria) will be silently dropped. However, if set to
<emphasis>true</emphasis> message rejection will result in an
error condition and the exception will be propagated upstream
to the caller.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-filter-xml08-co" id="xpath-filter-xml08">
<para>Reference to an XPath expression instance to evaluate.</para>
</callout>
<callout arearefs="xpath-filter-xml09-co" id="xpath-filter-xml09">
<para>
This sub-element sets the XPath expression to be evaluated. If
this is not defined you MUST define the <code> xpath-expression-ref</code>
attribute. Also, only one <code>xpath-expression</code> element
can be set.
</para>
</callout>
<callout arearefs="xpath-filter-xml10-co" id="xpath-filter-xml10">
<para>
<emphasis>Optional</emphasis>.
</para>
</callout>
</calloutlist></para>
</section>
<section id="xpath-spel-function">
<title>#xpath SpEL Function</title>
<para>
Spring Integration, since version <emphasis>3.0</emphasis>, provides the <code>#xpath</code>
built-in SpEL function, which invokes the static method <code>XPathUtils.evaluate(...)</code>.
This method delegates to an <interfacename>org.springframework.xml.xpath.XPathExpression</interfacename>.
The following shows some usage examples:
<programlisting language="xml"><![CDATA[<transformer expression="#xpath(payload, '/name')"/>
<filter expression="#xpath(payload, headers.xpath, 'boolean')"/>
<splitter expression="#xpath(payload, '//book', 'document_list')"/>
<router expression="#xpath(payload, '/person/@age', 'number')">
<mapping channel="output1" value="16"/>
<mapping channel="output2" value="45"/>
</router>]]></programlisting>
<code>#xpath</code> also supports a third optional parameter for converting the result of the xpath evaluation.
It can be
one of the String constants <code>'string'</code>, <code>'boolean'</code>, <code>'number'</code>,
<code>'node'</code>, <code>'node_list'</code> and <code>'document_list'</code> or an
<interfacename>org.springframework.xml.xpath.NodeMapper</interfacename> instance.
By default the <code>#xpath</code> SpEL function returns a String representation of the xpath evaluation.
</para>
<note>
To enable the <code>#xpath</code> SpEL function, simply add the <code>spring-integration-xml.jar</code>
to the CLASSPATH; there is no need to declare any component(s) from the Spring Integration Xml Namespace.
</note>
<para>
For more information see <xref linkend="spel"/>.
</para>
</section>
<section id="xml-validating-filter">
<title>XML Validating Filter</title>
<para>
The XML Validating Filter allows you to validate incoming messages against
provided schema instances. The following schema types are supported:
</para>
<itemizedlist>
<listitem>xml-schema (http://www.w3.org/2001/XMLSchema)</listitem>
<listitem>relax-ng (http://relaxng.org/ns/structure/1.0)</listitem>
</itemizedlist>
<para>
Messages that fail validation can either be
silently dropped or they can be forwarded to a definable <code>discard-channel</code>.
Furthermore you can configure this filter to throw an <code>Exception</code>
in case validation fails.
</para>
<para>
Please see below for an overview of all available configuration parameters:
</para>
<programlisting language="xml"><![CDATA[<int-xml:validating-filter discard-channel="" ]]><co id="xpath-validating-filter-xml01-co" linkends="xpath-validating-filter-xml01" /><![CDATA[
id="" ]]><co id="xpath-validating-filter-xml02-co" linkends="xpath-validating-filter-xml02" /><![CDATA[
input-channel="" ]]><co id="xpath-validating-filter-xml03-co" linkends="xpath-validating-filter-xml03" /><![CDATA[
output-channel="" ]]><co id="xpath-validating-filter-xml04-co" linkends="xpath-validating-filter-xml04" /><![CDATA[
schema-location="" ]]><co id="xpath-validating-filter-xml05-co" linkends="xpath-validating-filter-xml05" /><![CDATA[
schema-type="xml-schema" ]]><co id="xpath-validating-filter-xml06-co" linkends="xpath-validating-filter-xml06" /><![CDATA[
throw-exception-on-rejection="false" ]]><co id="xpath-validating-filter-xml07-co" linkends="xpath-validating-filter-xml07" /><![CDATA[
xml-validator=""> ]]><co id="xpath-validating-filter-xml08-co" linkends="xpath-validating-filter-xml08" /><![CDATA[
<int:poller .../> ]]><co id="xpath-validating-filter-xml09-co" linkends="xpath-validating-filter-xml09" /><![CDATA[
</int-xml:validating-filter>]]></programlisting>
<para>
<calloutlist>
<callout arearefs="xpath-validating-filter-xml01-co" id="xpath-validating-filter-xml01">
<para>
Message Channel where you want rejected messages to be sent.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-validating-filter-xml02-co" id="xpath-validating-filter-xml02">
<para>
Id for the underlying bean definition.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-validating-filter-xml03-co" id="xpath-validating-filter-xml03">
<para>The receiving Message channel of this endpoint. <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="xpath-validating-filter-xml04-co" id="xpath-validating-filter-xml04">
<para>
Message Channel where you want accepted messages to be sent. <emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-validating-filter-xml05-co" id="xpath-validating-filter-xml05">
<para>
Sets the location of the schema to validate the Message's payload against. Internally
uses the <interfacename>org.springframework.core.io.Resource</interfacename> interface.
You can set this attribute or the <code>xml-validator</code> attribute but not both.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-validating-filter-xml06-co" id="xpath-validating-filter-xml06">
<para>
Sets the schema type. Can be either <code>xml-schema</code> or <code>relax-ng</code>.
<emphasis>Optional</emphasis>. If not set it defaults
to <code>xml-schema</code> which internally translates to
<classname>org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML</classname>
</para>
</callout>
<callout arearefs="xpath-validating-filter-xml07-co" id="xpath-validating-filter-xml07">
<para>
If <code>true</code> a <classname>MessageRejectedException</classname> is thrown
in case validation fails for the provided Message's payload.
<emphasis>Optional</emphasis>. Defaults to <code>false</code> if not set.
</para>
</callout>
<callout arearefs="xpath-validating-filter-xml08-co" id="xpath-validating-filter-xml08">
<para>
Reference to a custom <interfacename>sorg.springframework.xml.validation.XmlValidator</interfacename> strategy.
You can set this attribute or the <code>schema-location</code> attribute but not both.
<emphasis>Optional</emphasis>.
</para>
</callout>
<callout arearefs="xpath-validating-filter-xml09-co" id="xpath-validating-filter-xml09">
<para>
<emphasis>Optional</emphasis>.
</para>
</callout>
</calloutlist>
</para>
</section>
</chapter>