* Mostly driver by suggestions from IDEA language plugin * Add Maven-Gradle code switch for dependency in the modules
1103 lines
53 KiB
Plaintext
1103 lines
53 KiB
Plaintext
[[xml]]
|
|
== XML Support - Dealing with XML Payloads
|
|
|
|
Spring Integration's XML support extends the core of Spring Integration with the following components:
|
|
|
|
* <<xml-transformation,Marshalling Transformer>>
|
|
* <<xml-transformation,Unmarshalling Transformer>>
|
|
* <<xml-transformation,XSLT Transformer>>
|
|
* <<xml-xpath-transformer,XPath Transformer>>
|
|
* <<xml-xpath-splitting,XPath Splitter>>
|
|
* <<xml-xpath-routing,XPath Router>>
|
|
* <<xml-xpath-header-enricher,XPath Header Enricher>>
|
|
* <<xml-xpath-filter,XPath Filter>>
|
|
* <<xpath-spel-function,#xpath SpEL Function>>
|
|
* <<xml-validating-filter,Validating Filter>>
|
|
|
|
You need to include this dependency into your project:
|
|
|
|
====
|
|
[source, xml, subs="normal", role="primary"]
|
|
.Maven
|
|
----
|
|
<dependency>
|
|
<groupId>org.springframework.integration</groupId>
|
|
<artifactId>spring-integration-xml</artifactId>
|
|
<version>{project-version}</version>
|
|
</dependency>
|
|
----
|
|
|
|
[source, groovy, subs="normal", role="secondary"]
|
|
.Gradle
|
|
----
|
|
compile "org.springframework.integration:spring-integration-xml:{project-version}"
|
|
----
|
|
====
|
|
|
|
These components make working with XML messages in Spring Integration simpler.
|
|
The messaging components work with XML that is represented in a range of formats, including instances of `java.lang.String`, `org.w3c.dom.Document`, and `javax.xml.transform.Source`.
|
|
However, where a DOM representation is required (for example, in order to evaluate an XPath expression), the `String` payload is converted into the required type and then converted back to `String`.
|
|
Components that require an instance of `DocumentBuilder` create a namespace-aware instance if you do not provide one.
|
|
When you require greater control over document creation, you can provide an appropriately configured instance of `DocumentBuilder`.
|
|
|
|
[[xpath-namespace-support]]
|
|
=== Namespace Support
|
|
|
|
All components within the Spring Integration XML module provide namespace support.
|
|
In order to enable namespace support, you need to import the schema for the Spring Integration XML Module.
|
|
The following example shows a typical setup:
|
|
|
|
====
|
|
[source,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"
|
|
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
|
|
https://www.springframework.org/schema/beans/spring-beans.xsd
|
|
http://www.springframework.org/schema/integration
|
|
https://www.springframework.org/schema/integration/spring-integration.xsd
|
|
http://www.springframework.org/schema/integration/xml
|
|
https://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd">
|
|
</beans>
|
|
----
|
|
====
|
|
|
|
[[xml-xpath-expressions]]
|
|
==== XPath Expressions
|
|
|
|
Many of the components within the Spring Integration XML module work with XPath Expressions.
|
|
Each of those components either references an XPath Expression that has been defined as a top-level element or uses a nested `<xpath-expression/>` element.
|
|
|
|
All forms of XPath expressions result in the creation of an `XPathExpression` that uses the Spring `org.springframework.xml.xpath.XPathExpressionFactory`.
|
|
When XPath expressions are created, the best XPath implementation that is available on the classpath is used (either JAXP 1.3+ or Jaxen, with JAXP being preferred).
|
|
|
|
NOTE: Internally, Spring Integration uses the XPath functionality provided by the Spring Web Services project (https://www.spring.io/spring-ws).
|
|
Specifically, we use the Spring Web Services XML module (spring-xml-x.x.x.jar).
|
|
For a deeper understanding, see the respective documentation at https://docs.spring.io/spring-ws/docs/current/reference/#xpath.
|
|
|
|
Here is an overview of all available configuration parameters of the `xpath-expression` element:
|
|
The following listing shows the available attributes for the `xpath-expression` element:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-expression expression="" <1>
|
|
id="" <2>
|
|
namespace-map="" <3>
|
|
ns-prefix="" <4>
|
|
ns-uri=""> <5>
|
|
<map></map> <6>
|
|
</int-xml:xpath-expression>
|
|
----
|
|
|
|
<1> Defines an XPath expression.
|
|
Required.
|
|
<2> The identifier of the underlying bean definition.
|
|
It is an instance of `org.springframework.xml.xpath.XPathExpression`.
|
|
Optional.
|
|
<3> Reference to a map that contains 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 `map` element or the `ns-prefix` and `ns-uri` attributes.
|
|
Optional.
|
|
<4> Lets you set the namespace prefix directly as an attribute on the XPath expression element.
|
|
If you set `ns-prefix`, you must also set the `ns-uri` attribute.
|
|
Optional.
|
|
<5> Lets you directly set the namespace URI as an attribute on the XPath expression element.
|
|
If you set `ns-uri`, you must also set the `ns-prefix` attribute.
|
|
Optional.
|
|
<6> Defines a map that contains 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.
|
|
It is not valid to specify both this element and the `map` attribute or set the `ns-prefix` and `ns-uri` attributes.
|
|
Optional.
|
|
====
|
|
|
|
===== Providing Namespaces (Optional) to XPath Expressions
|
|
|
|
For the XPath Expression Element, you can provide namespace information as configuration parameters.
|
|
You can define namespaces by using one of the following choices:
|
|
|
|
* Reference a map by using the `namespace-map` attribute
|
|
* Provide a map of namespaces by using the `map` sub-element
|
|
* Specify the `ns-prefix` and `ns-uri` attributes
|
|
|
|
All three options are mutually exclusive.
|
|
Only one option can be set.
|
|
|
|
The following example shows several different ways to use XPath expressions, including the options for setting the XML namespaces <<xpath-namespace-support,mentioned earlier>>:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<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>
|
|
----
|
|
====
|
|
|
|
===== Using XPath Expressions with Default Namespaces
|
|
|
|
When working with default namespaces, you may run into situations that behave differently than you might expect.
|
|
Assume we have the following XML document (which represents an order of two books):
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<?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>
|
|
----
|
|
====
|
|
|
|
This document does not declare a namespace.
|
|
Therefore, applying the following XPath Expression works as expected:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-expression expression="/order/orderItem" />
|
|
----
|
|
====
|
|
|
|
You might expect that the same expression also works for the following XML file:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<?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>
|
|
----
|
|
====
|
|
|
|
The preceding example looks exactly the same as the previous example but declares a default namespace.
|
|
|
|
However, the previous XPath expression (`/order/orderItem`) fails in this case.
|
|
|
|
In order to solve this issue, you must provide a namespace prefix and a namespace URI either by setting the `ns-prefix` and `ns-uri` attributes or by setting the `namespace-map` attribute.
|
|
The namespace URI must match the namespace declared in your XML document.
|
|
In the preceding example, that is `http://www.example.org/orders`.
|
|
|
|
You can, however, arbitrarily choose the namespace prefix.
|
|
In fact, providing an empty string actually works.
|
|
(However, null is not allowed.)
|
|
In the case of a namespace prefix consisting of an empty string, your Xpath expression must use a colon (":") to indicate the default namespace.
|
|
If you leave off the colon, the XPath expression does not match.
|
|
The following XPath Expression matches against the XML document in the preceding example:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-expression expression="/:order/:orderItem"
|
|
ns-prefix="" ns-uri="https://www.example.org/prodcuts"/>
|
|
----
|
|
====
|
|
|
|
You can also provide any other arbitrarily chosen namespace prefix.
|
|
The following XPath expression (which use the `myorder` namespace prefix) also matches:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-expression expression="/myorder:order/myorder:orderItem"
|
|
ns-prefix="myorder" ns-uri="https://www.example.org/prodcuts"/>
|
|
----
|
|
====
|
|
|
|
The namespace URI is the really important piece of information, not the prefix.
|
|
The https://github.com/jaxen-xpath/jaxen[Jaxen] summarizes the point very well:
|
|
|
|
[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.
|
|
|
|
[[xml-transformation]]
|
|
=== Transforming XML Payloads
|
|
|
|
This section covers how to transform XML payloads
|
|
|
|
[[xml-transformation-beans]]
|
|
==== Configuring Transformers as Beans
|
|
|
|
This section will explain the workings of the following transformers and how to configure them as beans:
|
|
|
|
* link:#xml-unmarshalling-transformer[UnmarshallingTransformer]
|
|
* link:#xml-marshalling-transformer[MarshallingTransformer]
|
|
* link:#xml-xslt-payload-transformers[XsltPayloadTransformer]
|
|
|
|
All the XML transformers extend either https://docs.spring.io/spring-integration/api/org/springframework/integration/transformer/AbstractTransformer.html[`AbstractTransformer`] or https://docs.spring.io/spring-integration/api/org/springframework/integration/transformer/AbstractPayloadTransformer.html[`AbstractPayloadTransformer`] and therefore implement https://docs.spring.io/spring-integration/api/org/springframework/integration/transformer/Transformer.html[`Transformer`].
|
|
When configuring XML transformers as beans in Spring Integration, you would normally configure the `Transformer` in conjunction with a https://docs.spring.io/spring-integration/api/org/springframework/integration/transformer/MessageTransformingHandler.html[`MessageTransformingHandler`].
|
|
This lets the transformer be used as an endpoint.
|
|
Finally, we discuss the namespace support, which allows for configuring the transformers as elements in XML.
|
|
|
|
[[xml-unmarshalling-transformer]]
|
|
===== UnmarshallingTransformer
|
|
|
|
An https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/UnmarshallingTransformer.html[`UnmarshallingTransformer`] lets an XML `Source` be unmarshalled by using implementations of the https://docs.spring.io/spring/docs/current/spring-framework-reference/html/oxm.html[Spring OXM] `Unmarshaller`.
|
|
Spring's Object/XML Mapping support provides several implementations that support marshalling and unmarshalling by using https://en.wikipedia.org/wiki/Java_Architecture_for_XML_Binding[JAXB], https://castor-data-binding.github.io/castor/reference-guide/reference/xml/xml-framework.html[Castor], https://en.wikipedia.org/wiki/JiBX[JiBX], and others.
|
|
The unmarshaller requires an instance of `Source`.
|
|
If the message payload is not an instance of `Source`, conversion is still attempted.
|
|
Currently, `String`, `File`, `byte[]` and `org.w3c.dom.Document` payloads are supported.
|
|
To create a custom conversion to a `Source`, you can inject an implementation of a https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/source/SourceFactory.html[`SourceFactory`].
|
|
|
|
NOTE: If you do not explicitly set a `SourceFactory`, the property on the `UnmarshallingTransformer` is, by default, set to a https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/source/DomSourceFactory.html[`DomSourceFactory`].
|
|
|
|
Starting with version 5.0, the `UnmarshallingTransformer` also supports an `org.springframework.ws.mime.MimeMessage` as the incoming payload.
|
|
This can be useful when we receive a raw `WebServiceMessage` with MTOM attachments over SOAP .
|
|
See <<./ws.adoc#mtom-support,MTOM Support>> for more information.
|
|
|
|
The following example shows how to define an unmarshalling transformer:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<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>
|
|
----
|
|
====
|
|
|
|
[[xml-marshalling-transformer]]
|
|
===== Using `MarshallingTransformer`
|
|
|
|
The https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/MarshallingTransformer.html[`MarshallingTransformer`] lets an object graph be converted into XML by using a Spring OXM `Marshaller`.
|
|
By default, the `MarshallingTransformer` returns a `DomResult`.
|
|
However, you can control the type of result by configuring an alternative `ResultFactory`, such as `StringResultFactory`.
|
|
In many cases, it is more convenient to transform the payload into an alternative XML format.
|
|
To do so, configure a `ResultTransformer`.
|
|
Spring integration provides two implementations, one that converts to `String` and another that converts to `Document`.
|
|
The following example configures a marshalling transformer that transforms to a document:
|
|
|
|
[source,xml]
|
|
----
|
|
<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>
|
|
----
|
|
|
|
By default, the `MarshallingTransformer` passes the payload object to the `Marshaller`.
|
|
However, if its boolean `extractPayload` property is set to `false`, the entire `Message` instance is passed to the `Marshaller` instead.
|
|
That may be useful for certain custom implementations of the `Marshaller` interface, but, typically, the payload is the appropriate source object for marshalling when you delegate to any of the various `Marshaller` implementations.
|
|
|
|
[[xml-xslt-payload-transformers]]
|
|
===== XsltPayloadTransformer
|
|
|
|
The https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/XsltPayloadTransformer.html[`XsltPayloadTransformer`] transforms XML payloads by using https://en.wikipedia.org/wiki/XSL_Transformations[Extensible Stylesheet Language Transformations] (XSLT).
|
|
The transformer's constructor requires an instance of either https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/Resource.html[Resource] or https://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Templates.html[Templates] to be passed in.
|
|
Passing in a `Templates` instance allows for greater configuration of the `TransformerFactory` used to create the template instance.
|
|
|
|
As with the link:#xml-unmarshalling-transformer[`UnmarshallingTransformer`], the `XsltPayloadTransformer` does the actual XSLT transformation against instances of `Source`.
|
|
Therefore, if the message payload is not an instance of `Source`, conversion is still attempted.
|
|
`String` and `Document` payloads are supported directly.
|
|
|
|
To create a custom conversion to a `Source`, you can inject an implementation of a https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/source/SourceFactory.html[`SourceFactory`].
|
|
|
|
NOTE: If a `SourceFactory` is not set explicitly, the property on the `XsltPayloadTransformer` is, by default, set to a https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/source/DomSourceFactory.html[`DomSourceFactory`].
|
|
|
|
By default, the `XsltPayloadTransformer` creates a message with a https://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Result.html[`Result`] payload, similar to the `XmlPayloadMarshallingTransformer`.
|
|
You can customize this by providing a https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/result/ResultFactory.html[`ResultFactory`] or a https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/ResultTransformer.html[`ResultTransformer`].
|
|
|
|
The following example configures a bean that works as an XSLT payload transformer:
|
|
|
|
[source,xml]
|
|
----
|
|
<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>
|
|
----
|
|
|
|
Starting with Spring Integration 3.0, you can specify the transformer factory class name by using a constructor argument.
|
|
You can do so by using the `transformer-factory-class` attribute when you use the namespace.
|
|
|
|
[[xml-using-result-transformers]]
|
|
===== Using `ResultTransformer` Implementations
|
|
|
|
Both the `MarshallingTransformer` and the `XsltPayloadTransformer` let you specify a https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/ResultTransformer.html[`ResultTransformer`].
|
|
Thus, if the marshalling or XSLT transformation returns a https://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Result.html[`Result`], you have the option to also use a `ResultTransformer` to transform the `Result` into another format.
|
|
Spring Integration provides two concrete `ResultTransformer` implementations:
|
|
|
|
* https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/ResultToDocumentTransformer.html[`ResultToDocumentTransformer`]
|
|
* https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/ResultToStringTransformer.html[`ResultToStringTransformer`]
|
|
|
|
By default, the `MarshallingTransformer` always returns a https://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Result.html[`Result`].
|
|
By specifying a `ResultTransformer`, you can customize the type of payload returned.
|
|
|
|
The behavior is slightly more complex for the `XsltPayloadTransformer`.
|
|
By default, if the input payload is an instance of `String` or https://docs.oracle.com/javase/6/docs/api/org/w3c/dom/Document.html[`Document`] the `resultTransformer` property is ignored.
|
|
|
|
However, if the input payload is a https://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Source.html[`Source`] or any other type, the `resultTransformer` property is applied.
|
|
Additionally, you can set the `alwaysUseResultFactory` property to `true`, which also causes the specified `resultTransformer` to be used.
|
|
|
|
For more information and examples, see <<xml-using-result-transformers-namespace>>.
|
|
|
|
[[xml-transformer-namespace]]
|
|
==== Namespace Support for XML Transformers
|
|
|
|
Namespace support for all XML transformers is provided in the Spring Integration XML namespace, a template for which was <<xpath-namespace-support,shown earlier>>.
|
|
The namespace support for transformers creates an instance of either `EventDrivenConsumer` or `PollingConsumer`, 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 that use one element.
|
|
|
|
===== Using an `UnmarshallingTransformer`
|
|
|
|
The namespace support for the `UnmarshallingTransformer` is shown below.
|
|
Since the namespace create an endpoint instance rather than a transformer, you can nest a poller within the element to control the polling of the input channel.
|
|
The following example shows how to do so:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<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/>
|
|
----
|
|
====
|
|
|
|
===== Using a `MarshallingTransformer`
|
|
|
|
The namespace support for the marshalling transformer requires an `input-channel`, an `output-channel`, and a reference to a `marshaller`.
|
|
You can use the optional `result-type` attribute to control the type of result created.
|
|
Valid values are `StringResult` or `DomResult` (the default).
|
|
The following example configures a marshalling transformer:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<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"/>
|
|
----
|
|
====
|
|
|
|
Where the provided result types do not suffice, you can provide a reference to a custom implementation of `ResultFactory` as an alternative to setting the `result-type` attribute by using the `result-factory` attribute.
|
|
The `result-type` and `result-factory` attributes are mutually exclusive.
|
|
|
|
NOTE: Internally, the `StringResult` and `DomResult` result types are represented by the `ResultFactory` implementations: https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/result/StringResultFactory.html[`StringResultFactory`] and https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/result/DomResultFactory.html[`DomResultFactory`] respectively.
|
|
|
|
===== Using an `XsltPayloadTransformer`
|
|
|
|
Namespace support for the `XsltPayloadTransformer` lets you either pass in a `Resource` (in order to create the https://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Templates.html[`Templates`] instance) or pass in a pre-created `Templates` instance as a reference.
|
|
As with the marshalling transformer, you can control the type of the result output by specifying either the `result-factory` or the `result-type` attribute.
|
|
When you need to convert result before sending, you can use a `result-transformer` attribute to reference an implementation of `ResultTransformer`.
|
|
|
|
IMPORTANT: If you specify the `result-factory` or the `result-type` attribute, the `alwaysUseResultFactory` property on the underlying https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/XsltPayloadTransformer.html[`XsltPayloadTransformer`] is set to `true` by the https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/config/XsltPayloadTransformerParser.html[`XsltPayloadTransformerParser`].
|
|
|
|
The following example configures two XSLT transformers:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<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"/>
|
|
----
|
|
====
|
|
|
|
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 (for example, `transformer.setParameter(..)`).
|
|
Spring Integration provides two convenient ways to accomplish this, as the following example shows:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<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>
|
|
----
|
|
====
|
|
|
|
If message header names match one-to-one to parameter names, you can use the `xslt-param-headers` attribute.
|
|
In it, you can use wildcards for simple pattern matching.
|
|
It supports the following simple pattern styles: `xxx*`, `*xxx`, `*xxx*`, and `xxx*yyy`.
|
|
|
|
You can also configure individual XSLT parameters by using the `<xslt-param/>` element.
|
|
On that element, you can set the `expression` attribute or the `value` attribute.
|
|
The `expression` attribute should be any valid SpEL expression with the `Message` being the root object of the expression evaluation context.
|
|
The `value` attribute (as with any `value` in Spring beans) lets you specify simple scalar values.
|
|
You can also use property placeholders (such as `${some.value}`).
|
|
So, with the `expression` and `value` attributes, you can map XSLT parameters to any accessible part of the `Message` as well as any literal value.
|
|
|
|
Starting with Spring Integration 3.0, you can now specify the transformer factory class name by setting the `transformer-factory-class` attribute.
|
|
|
|
[[xml-using-result-transformers-namespace]]
|
|
==== Namespace Configuration and Result Transformers
|
|
|
|
We cover using result transformers in <<xml-using-result-transformers>>.
|
|
The examples in this section use XML namespace configuration to illustrates several special use cases.
|
|
First, we define the `ResultTransformer`, as the following example shows:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<beans:bean id="resultToDoc" class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
|
|
----
|
|
====
|
|
|
|
This `ResultTransformer` accepts either a `StringResult` or a `DOMResult` as input and converts the input into a `Document`.
|
|
|
|
Now we can declare the transformer, as follows:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
|
|
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"/>
|
|
----
|
|
====
|
|
|
|
If the incoming message's payload is of type `Source`, then, as a first step, the `Result` is determined by using the `ResultFactory`.
|
|
As we did not specify a `ResultFactory`, the default `DomResultFactory` is used, meaning that the transformation yields a `DomResult`.
|
|
|
|
However, as we specified a `ResultTransformer`, it is used and the resulting `Message` payload is of type `Document`.
|
|
|
|
IMPORTANT: The specified `ResultTransformer` is ignored with `String` or `Document` payloads.
|
|
If the incoming message's payload is of type `String`, the payload after the XSLT transformation is a `String`.
|
|
Similarly, if the incoming message's payload is of type `Document`, the payload after the XSLT transformation is a`Document`.
|
|
|
|
If the message payload is not a `Source`, a `String`, or a `Document`, as a fallback option, we try to create a`Source` by using the default https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/source/SourceFactory.html[`SourceFactory`].
|
|
As we did not specify a `SourceFactory` explicitly by using the `source-factory` attribute, the default https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/source/DomSourceFactory.html[`DomSourceFactory`] is used.
|
|
If successful, the XSLT transformation is executed as if the payload was of type `Source`, as described in the previous paragraphs.
|
|
|
|
NOTE: The `DomSourceFactory` supports the creation of a `DOMSource` from a `Document`, a `File`, or a `String` payload.
|
|
|
|
The next transformer declaration adds a `result-type` attribute that uses `StringResult` as its value.
|
|
The `result-type` is internally represented by the `StringResultFactory`.
|
|
Thus, you could have also added a reference to a `StringResultFactory`, by using the `result-factory` attribute, which would have been the same.
|
|
The following example shows that transformer declaration:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
|
|
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"
|
|
result-type="StringResult"/>
|
|
----
|
|
====
|
|
|
|
Because we use a `ResultFactory`, the `alwaysUseResultFactory` property of the `XsltPayloadTransformer` class is implicitly set to `true`.
|
|
Consequently, the referenced `ResultToDocumentTransformer` is used.
|
|
|
|
Therefore, if you transform a payload of type `String`, the resulting payload is of type https://docs.oracle.com/javase/6/docs/api/org/w3c/dom/Document.html[`Document`].
|
|
|
|
===== `XsltPayloadTransformer` and `<xsl:output method="text"/>`
|
|
|
|
`<xsl:output method="text"/>` tells the XSLT template to produce only text content from the input source.
|
|
In this particular case, we have no reason to use a `DomResult`.
|
|
Therefore, the https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/XsltPayloadTransformer.html[`XsltPayloadTransformer`] defaults to `StringResult` if the https://docs.oracle.com/javase/7/docs/api/javax/xml/transform/Transformer.html#getOutputProperties()[output property] called `method` of the underlying `javax.xml.transform.Transformer` returns `text`.
|
|
This coercion is performed independently from the inbound payload type.
|
|
This behavior is available only you set the if the `result-type` attribute or the `result-factory` attribute for the `<int-xml:xslt-transformer>` component.
|
|
|
|
[[xml-xpath-transformer]]
|
|
=== Transforming XML Messages with XPath
|
|
|
|
When it comes to message transformation, XPath is a great way to transform messages that have XML payloads.
|
|
You can do so by defining XPath transformers with the `<xpath-transformer/>` element.
|
|
|
|
==== Simple XPath Transformation
|
|
|
|
Consider following transformer configuration:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-transformer input-channel="inputChannel" output-channel="outputChannel"
|
|
xpath-expression="/person/@name" />
|
|
----
|
|
====
|
|
|
|
Also consider the following `Message`:
|
|
|
|
====
|
|
[source,java]
|
|
----
|
|
Message<?> message =
|
|
MessageBuilder.withPayload("<person name='John Doe' age='42' married='true'/>").build();
|
|
----
|
|
====
|
|
|
|
After sending this message to the 'inputChannel', the XPath transformer configured earlier transforms this XML Message to a simple `Message` with a payload of 'John Doe', all based on the simple XPath Expression specified in the `xpath-expression` attribute.
|
|
|
|
XPath also lets you perform simple conversion of an extracted element to a desired type.
|
|
Valid return types are defined in `javax.xml.xpath.XPathConstants` and follow the conversion rules specified by the `javax.xml.xpath.XPath` interface.
|
|
|
|
The following constants are defined by the `XPathConstants` class: `BOOLEAN`, `DOM_OBJECT_MODEL`, `NODE`, `NODESET`, `NUMBER`, and `STRING`.
|
|
|
|
You can configure the desired type by using the `evaluation-type` attribute of the `<xpath-transformer/>` element, as the following example shows (twice):
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<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"/>
|
|
----
|
|
====
|
|
|
|
==== Node Mappers
|
|
|
|
If you need to provide custom mapping for the node extracted by the XPath expression, you can provide a reference to the implementation of the `org.springframework.xml.xpath.NodeMapper` (an interface used by `XPathOperations` implementations for mapping `Node` objects on a per-node basis).
|
|
To provide a reference to a `NodeMapper`, you can use the `node-mapper` attribute, as the following example shows:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-transformer input-channel="nodeMapperInput" xpath-expression="/person/@age"
|
|
node-mapper="testNodeMapper" output-channel="output"/>
|
|
----
|
|
====
|
|
|
|
The following example shows a `NodeMapper` implementation that works with the preceding example:
|
|
|
|
====
|
|
[source,java]
|
|
----
|
|
class TestNodeMapper implements NodeMapper {
|
|
public Object mapNode(Node node, int nodeNum) throws DOMException {
|
|
return node.getTextContent() + "-mapped";
|
|
}
|
|
}
|
|
----
|
|
====
|
|
|
|
==== XML Payload Converter
|
|
|
|
You can also use an implementation of the `org.springframework.integration.xml.XmlPayloadConverter` to provide more granular transformation.
|
|
The following example shows how to define one:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-transformer input-channel="customConverterInput"
|
|
output-channel="output" xpath-expression="/test/@type"
|
|
converter="testXmlPayloadConverter" />
|
|
----
|
|
====
|
|
|
|
The following example shows an `XmlPayloadConverter` implementation that works with the preceding example:
|
|
|
|
====
|
|
[source,java]
|
|
----
|
|
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();
|
|
}
|
|
}
|
|
----
|
|
====
|
|
|
|
If you do not provide this reference, the `DefaultXmlPayloadConverter` is used.
|
|
It should suffice in most cases, because it can convert from `Node`, `Document`, `Source`, `File`, `String`, `InputStream`, and `byte[]` payloads.
|
|
If you need to extend beyond the capabilities of that default implementation, an upstream `Transformer` is probably a better option than providing a reference to a custom implementation of this strategy here.
|
|
|
|
[[xml-xpath-splitting]]
|
|
=== Splitting XML Messages
|
|
|
|
`XPathMessageSplitter` supports messages with either `String` or `Document` payloads.
|
|
The splitter uses the provided XPath expression to split the payload into a number of nodes.
|
|
By default, this results in each `Node` instance becoming the payload of a new message.
|
|
When each message should be a `Document`, you can set the `createDocuments` flag.
|
|
Where a `String` payload is passed in, the payload is converted and then split before being converted back to a number of `String` messages.
|
|
The XPath splitter implements `MessageHandler` and should therefore be configured in conjunction with an appropriate endpoint (see the namespace support example after the following example for a simpler configuration alternative).
|
|
The following example configures a bean that uses an `XPathMessageSplitter`:
|
|
|
|
[source,xml]
|
|
----
|
|
<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>
|
|
----
|
|
|
|
XPath splitter namespace support lets you create a message endpoint with an input channel and output channel, as the following example shows:
|
|
|
|
[source,xml]
|
|
----
|
|
<!-- Split the order into items and create 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, create 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>
|
|
----
|
|
|
|
Starting with version 4.2, the `XPathMessageSplitter` exposes the `outputProperties` (such as `OutputKeys.OMIT_XML_DECLARATION`) property for an `javax.xml.transform.Transformer` instance when a request `payload` is not of type `org.w3c.dom.Node`.
|
|
The following example defines a property and uses it with the `output-properties` property:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<util:properties id="outputProperties">
|
|
<beans:prop key="#{T (javax.xml.transform.OutputKeys).OMIT_XML_DECLARATION}">yes</beans:prop>
|
|
</util:properties>
|
|
|
|
<xpath-splitter input-channel="input"
|
|
output-properties="outputProperties">
|
|
<xpath-expression expression="/orders/order"/>
|
|
</xpath-splitter>
|
|
----
|
|
====
|
|
|
|
Starting with `version 4.2`, the `XPathMessageSplitter` exposes an `iterator` option as a `boolean` flag (defaults to `true`).
|
|
This allows the "`streaming`" of split nodes in the downstream flow.
|
|
With the `iterator` mode set to `true`, each node is transformed while iterating.
|
|
When `false`, all entries are first transformed, before the split nodes start being sent to the output channel.
|
|
(You can think of the difference as "`transform, send, transform, send`" versus "`transform, transform, send, send`".)
|
|
See <<./splitter.adoc#splitter,Splitter>> for more information.
|
|
|
|
[[xml-xpath-routing]]
|
|
=== Routing XML Messages with XPath
|
|
|
|
Similar to SpEL-based routers, Spring Integration provides support for routing messages based on XPath expressions, which lets you create a message endpoint with an input channel but no output channel.
|
|
Instead, one or more output channels are determined dynamically.
|
|
The following example shows how to create such a router:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-router id="orderTypeRouter" input-channel="orderChannel">
|
|
<int-xml:xpath-expression expression="/order/type"/>
|
|
</int-xml:xpath-router>
|
|
----
|
|
====
|
|
|
|
NOTE: For an overview of attributes that are common among Routers, see <<./router.adoc#router-common-parameters,Common Router Parameters>>.
|
|
|
|
Internally, XPath expressions are evaluated as type `NODESET` and converted to a `List<String>` that represents channel names.
|
|
Typically, such a list contains a single channel name.
|
|
However, based on the results of an XPath Expression, the XPath router can also take on the characteristics of a recipient list router if the XPath expression returns more than one value.
|
|
In that case, the `List<String>` contains more than one channel name.
|
|
Consequently, messages are sent to all the channels in the list.
|
|
|
|
Thus, assuming that the XML file passed to the following router configuration contains many `responder` sub-elements that represent channel names, the message is sent to all of those channels:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<!-- 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>
|
|
|
|
----
|
|
====
|
|
|
|
If the returned values do not represent the channel names directly, you can specify additional mapping parameters to map those returned values to actual channel names.
|
|
For example if the `/request/responders` expression results in two values (`responderA` and `responderB`), but you do not want to couple the responder names to channel names, you can provide additional mapping configuration, such as the following:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<!-- 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>
|
|
|
|
----
|
|
====
|
|
|
|
As already mentioned, the default evaluation type for XPath expressions is `NODESET`, which is converted to a `List<String>` of channel names, which handles single channel scenarios as well as multiple channel scenarios.
|
|
|
|
Nonetheless, certain XPath expressions may evaluate as type `String` from the very beginning.
|
|
Consider, for example, the following XPath Expression:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
name(./node())
|
|
----
|
|
====
|
|
|
|
This expression returns the name of the root node.
|
|
If the default evaluation type `NODESET` is being used, it results in an exception.
|
|
|
|
For these scenarios, you can use the `evaluate-as-string` attribute, which lets you manage the evaluation type.
|
|
It is `FALSE` by default.
|
|
However, if you set it to `TRUE`, the `String` evaluation type is used.
|
|
|
|
[NOTE]
|
|
=====
|
|
XPath 1.0 specifies 4 data types:
|
|
|
|
* Node-sets
|
|
* Strings
|
|
* Number
|
|
* Boolean
|
|
|
|
When the XPath Router evaluates expressions by using the optional `evaluate-as-string` attribute, the return value is determined by the `string()` function, as defined in the XPath specification.
|
|
This means that, if the expression selects multiple nodes, it return the string value of the first node.
|
|
|
|
For further information, see:
|
|
|
|
* https://www.w3.org/TR/xpath/[Specification: XML Path Language (XPath) Version 1.0]
|
|
* https://www.w3.org/TR/xpath-functions-31[XPath specification - string() function]
|
|
=====
|
|
|
|
For example, if we want to route based on the name of the root node, we can use the following configuration:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-router id="xpathRouterAsString"
|
|
input-channel="xpathStringChannel"
|
|
evaluate-as-string="true">
|
|
<int-xml:xpath-expression expression="name(./node())"/>
|
|
</int-xml:xpath-router>
|
|
|
|
----
|
|
====
|
|
|
|
[[xpath-routing-converter]]
|
|
==== XML Payload Converter
|
|
|
|
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 `XmlPayloadConverter` strategy, and when configuring an `xpath-router` element in XML, a reference to such an implementation may be provided via the `converter` attribute.
|
|
|
|
If this reference is not explicitly provided, the `DefaultXmlPayloadConverter` 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.
|
|
|
|
[[xml-xpath-header-enricher]]
|
|
=== XPath Header Enricher
|
|
|
|
The XPath header enricher defines a header enricher message transformer that evaluates an XPath expression against the message payload and inserts the result of the evaluation into a message header.
|
|
|
|
The following listing shows all the available configuration parameters:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-header-enricher default-overwrite="true" <1>
|
|
id="" <2>
|
|
input-channel="" <3>
|
|
output-channel="" <4>
|
|
should-skip-nulls="true"> <5>
|
|
<int:poller></int:poller> <6>
|
|
<int-xml:header name="" <7>
|
|
evaluation-type="STRING_RESULT" <8>
|
|
header-type="int" <9>
|
|
overwrite="true" <10>
|
|
xpath-expression="" <11>
|
|
xpath-expression-ref=""/> <12>
|
|
</int-xml:xpath-header-enricher>
|
|
|
|
----
|
|
|
|
<1> Specifies the default boolean value for whether to overwrite existing header values.
|
|
It takes effect only for child elements that do not provide their own 'overwrite' attribute.
|
|
If you do not set the 'default- overwrite' attribute, the specified header values do not overwrite any existing ones with the same header names.
|
|
Optional.
|
|
<2> ID for the underlying bean definition.
|
|
Optional.
|
|
<3> The receiving message channel of this endpoint.
|
|
Optional.
|
|
<4> Channel to which enriched messages are sent.
|
|
Optional.
|
|
<5> Specifies whether null values, such as might be returned from an expression evaluation, should be skipped.
|
|
The default value is `true`.
|
|
If a null value should trigger removal of the corresponding header, set this to `false`.
|
|
Optional.
|
|
<6> A poller to use with the header enricher.
|
|
Optional.
|
|
<7> The name of the header to be enriched.
|
|
Mandatory.
|
|
<8> The result type expected from the XPath evaluation.
|
|
If you did not set a `header-type` attribute, this is the type of the header value.
|
|
The following values are allowed: `BOOLEAN_RESULT`, `STRING_RESULT`, `NUMBER_RESULT`, `NODE_RESULT`, and `NODE_LIST_RESULT`.
|
|
If not set, it defaults internally to `XPathEvaluationType.STRING_RESULT`.
|
|
Optional.
|
|
<9> The fully qualified class name for the header value type.
|
|
The result of the XPath evaluation is converted to this type by `ConversionService`.
|
|
This allows, for example, a `NUMBER_RESULT` (a double) to be converted to an `Integer`.
|
|
The type can be declared as a primitive (such as `int`), but the result is always the equivalent wrapper class (such as `Integer`).
|
|
The same integration `ConversionService` discussed in <<./endpoint.adoc#payload-type-conversion,Payload Type Conversion>> is used for the conversion, so conversion to custom types is supported by adding a custom converter to the service.
|
|
Optional.
|
|
<10> 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`.
|
|
<11> The XPath expression as a `String`.
|
|
You must set either this attribute or `xpath-expression-ref`, but not both.
|
|
<12> The XPath expression reference.
|
|
You must set either this attribute or `xpath-expression`, but not both.
|
|
====
|
|
|
|
[[xml-xpath-filter]]
|
|
=== Using the XPath Filter
|
|
|
|
This component defines an XPath-based message filter.
|
|
Internally, these components uses a `MessageFilter` that wraps an instance of `AbstractXPathMessageSelector`.
|
|
|
|
NOTE: See <<./filter.adoc#filter,Filter>> for further details.
|
|
|
|
to use the XPath filter you must, at a minimum, provide an XPath expression either by declaring the `xpath-expression` element or by referencing an XPath Expression in the `xpath-expression-ref` attribute.
|
|
|
|
If the provided XPath expression evaluates to a `boolean` value, no further configuration parameters are necessary.
|
|
However, if the XPath expression evaluates to a `String`, you should set the `match-value` attribute, against which the evaluation result is matched.
|
|
|
|
`match-type` has three options:
|
|
|
|
* `exact`: Correspond to `equals` on `java.lang.String`.
|
|
The underlying implementation uses a `StringValueTestXPathMessageSelector`
|
|
|
|
* `case-insensitive`: Correspond to `equals-ignore-case` on `java.lang.String`.
|
|
The underlying implementation uses a `StringValueTestXPathMessageSelector`
|
|
|
|
* `regex`: Matches operations one `java.lang.String`.
|
|
The underlying implementation uses a `RegexTestXPathMessageSelector`
|
|
|
|
When providing a 'match-type' value of 'regex', the value provided with the `match-value` attribute must be a valid regular expression.
|
|
|
|
The following example shows all the available attributes for the `xpath-filter` element:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:xpath-filter discard-channel="" <1>
|
|
id="" <2>
|
|
input-channel="" <3>
|
|
match-type="exact" <4>
|
|
match-value="" <5>
|
|
output-channel="" <6>
|
|
throw-exception-on-rejection="false" <7>
|
|
xpath-expression-ref=""> <8>
|
|
<int-xml:xpath-expression ... /> <9>
|
|
<int:poller ... /> <10>
|
|
</int-xml:xpath-filter>
|
|
----
|
|
|
|
<1> Message channel where you want rejected messages to be sent.
|
|
Optional.
|
|
<2> ID for the underlying bean definition.
|
|
Optional.
|
|
<3> The receiving message channel of this endpoint.
|
|
Optional.
|
|
<4> Type of match to apply between the XPath evaluation result and the `match-value`.
|
|
The default is `exact`.
|
|
Optional.
|
|
<5> String value to be matched against the XPath evaluation result.
|
|
If you do not set this attribute, the XPath evaluation must produce a boolean result.
|
|
Optional.
|
|
<6> The channel to which messages that matched the filter criteria are dispatched.
|
|
Optional.
|
|
<7> By default, this property is set to `false` and rejected messages (those did not match the filter criteria) are silently dropped.
|
|
However, if set to `true`, message rejection results in an error condition and an exception being propagated upstream to the caller.
|
|
Optional.
|
|
<8> Reference to an XPath expression instance to evaluate.
|
|
<9> This child element sets the XPath expression to be evaluated.
|
|
If you do not include this element, you must set the `xpath-expression-ref` attribute.
|
|
Also, you can include only one `xpath-expression` element.
|
|
<10> A poller to use with the XPath filter.
|
|
Optional.
|
|
====
|
|
|
|
[[xpath-spel-function]]
|
|
=== #xpath SpEL Function
|
|
|
|
Spring Integration, since version 3.0, provides the built-in `#xpath` SpEL function, which invokes the `XPathUtils.evaluate(...)` static method.
|
|
This method delegates to an `org.springframework.xml.xpath.XPathExpression`.
|
|
The following listing shows some usage examples:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<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>
|
|
----
|
|
====
|
|
|
|
The `#xpath()` also supports a third optional parameter for converting the result of the XPath evaluation.
|
|
It can be one of the String constants (`string`, `boolean`, `number`, `node`, `node_list` and `document_list`) or an `org.springframework.xml.xpath.NodeMapper` instance.
|
|
By default, the `#xpath` SpEL function returns a `String` representation of the XPath evaluation.
|
|
|
|
NOTE: To enable the `#xpath` SpEL function, you can add the `spring-integration-xml.jar` to the classpath.
|
|
You need no declare any components from the Spring Integration XML Namespace.
|
|
|
|
For more information, see "`<<./spel.adoc#spel,Spring Expression Language (SpEL)>>.
|
|
|
|
[[xml-validating-filter]]
|
|
=== XML Validating Filter
|
|
|
|
The XML Validating Filter lets you validate incoming messages against provided schema instances.
|
|
The following schema types are supported:
|
|
|
|
* xml-schema (https://www.w3.org/2001/XMLSchema)
|
|
* relax-ng (https://relaxng.org)
|
|
|
|
Messages that fail validation can either be silently dropped or be forwarded to a definable `discard-channel`.
|
|
Furthermore, you can configure this filter to throw an `Exception` in case validation fails.
|
|
|
|
The following listing shows all the available configuration parameters:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int-xml:validating-filter discard-channel="" <1>
|
|
id="" <2>
|
|
input-channel="" <3>
|
|
output-channel="" <4>
|
|
schema-location="" <5>
|
|
schema-type="xml-schema" <6>
|
|
throw-exception-on-rejection="false" <7>
|
|
xml-converter="" <8>
|
|
xml-validator=""> <9>
|
|
<int:poller .../> <10>
|
|
</int-xml:validating-filter>
|
|
----
|
|
|
|
<1> Message channel where you want rejected messages to be sent.
|
|
Optional.
|
|
<2> ID for the underlying bean definition.
|
|
Optional.
|
|
<3> The receiving message channel of this endpoint.
|
|
Optional.
|
|
<4> Message channel where you want accepted messages to be sent.
|
|
Optional.
|
|
<5> Sets the location of the schema to validate the message's payload against.
|
|
Internally uses the `org.springframework.core.io.Resource` interface.
|
|
You can set this attribute or the `xml-validator` attribute but not both.
|
|
Optional.
|
|
<6> Sets the schema type.
|
|
Can be either `xml-schema` or `relax-ng`.
|
|
Optional.
|
|
If not set, it defaults to `xml-schema`, which internally translates to `org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML`.
|
|
<7> If `true`, a `MessageRejectedException` is thrown if validation fails for the provided Message's payload.
|
|
Defaults to `false` if not set.
|
|
Optional.
|
|
<8> Reference to a custom `org.springframework.integration.xml.XmlPayloadConverter` strategy.
|
|
Optional.
|
|
<9> Reference to a custom `sorg.springframework.xml.validation.XmlValidator` strategy.
|
|
You can set this attribute or the `schema-location` attribute but not both.
|
|
Optional.
|
|
<10> A poller to use with the XPath filter.
|
|
Optional.
|
|
====
|