[[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]]
== 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]]
== 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]]
== 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.

