Camel Components

XML Tokenize

Since Camel 2.14

The XML Tokenize language (xtokenize) is a tokenizer specifically designed for XML documents. Unlike the conventional Tokenize language, which is primarily a text-based tokenizer, XML Tokenize uses a StAX parser to interpret the XML structure while producing tokens.

The conventional Tokenize language also provides an xml option for XML-aware tokenization (xml=true). This should not be confused with XML Tokenize: xtokenize uses different tokenization semantics and is intended for different use cases.

Use xtokenize when XML structure or namespaces are important, or when you want a tokenizer specifically designed for XML documents. Use the conventional Tokenize language when you primarily need text-based tokenization and XML awareness is sufficient for your use case.

Maven users will need to add the following dependency to their pom.xml for this language:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-stax</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>

XML Tokenizer Options

The XML Tokenize language supports the following options which are listed below.

Name Default Java Type Description

mode (common)

i

Enum

The extraction mode. The available extraction modes are: i - injecting the contextual namespace bindings into the extracted token (default), w - wrapping the extracted token in its ancestor context, u - unwrapping the extracted token to its child content, t - extracting the text content of the specified element.

Enum values:

  • i

  • w

  • u

  • t

group (common)

Integer

To group N parts together.

namespacesRef (advanced)

String

Reference to a org.apache.camel.support.builder.Namespaces bean in the registry to use for the XML Namespaces of prefix to uri mappings.

source (common)

String

Source to use, instead of message body. You can prefix with variable:, header:, or property: to specify kind of source. Otherwise, the source is assumed to be a variable. Use empty or null to use default source, which is the message body.

resultType (common)

String

The class of the result type (type from output).

trim (advanced)

true

Boolean

Whether to trim the source code to remove leading and trailing whitespaces and line breaks.

resolveResource (advanced)

false

Boolean

Whether a result of the expression that is a String starting with resource: is loaded as a resource and its content becomes the result, e.g. a script that returns resource:file:order.json or resource:classpath:templates/order.json (a name without a scheme is a classpath resource). Off by default; the resource: prefix on the expression text itself is always resolved. Applies to the expression used as a value, not as a predicate.

Message Body

The message body at each side of the XML Tokenize language: Expression input is the body its expressions can read, and Expression result what they return.

Side Body Description

Expression input

text, bytes, stream, file or pojo, as xml

XML as text, bytes, a stream or a file, or a DOM.

Not known when source is set.

Expression result

iterator

An Iterator of the elements the path matches as XML text, read once; mode t gives their text. With group, each N elements are joined into one text.

The bodies are the ones with the default options. A side that is not listed is not known, and tooling does not guess it. The carriers are described in the Camel Catalog.

Namespaces

The XML Tokenize language is namespace aware, so a tokenized element can be selected by its prefix. The prefix to URI mappings can be declared inline, or shared across several expressions by registering a org.apache.camel.support.builder.Namespaces bean and referring to it with the namespacesRef option:

  • Java

  • XML

  • YAML

@BindToRegistry("myNamespaces")
Namespaces myNamespaces = new Namespaces("c", "http://acme.com/cheese");

from("file:inbox")
    .split(expression().xtokenize("//c:order").namespacesRef("myNamespaces").end())
        .to("mock:result");
<camel xmlns="http://camel.apache.org/schema/xml-io">

  <bean name="myNamespaces" type="org.apache.camel.support.builder.Namespaces">
    <properties>
      <property key="namespaces[c]" value="http://acme.com/cheese"/>
    </properties>
  </bean>

  <route>
    <from uri="file:inbox"/>
    <split>
      <xtokenize namespacesRef="myNamespaces">//c:order</xtokenize>
      <to uri="mock:result"/>
    </split>
  </route>

</camel>
- beans:
    - name: myNamespaces
      type: org.apache.camel.support.builder.Namespaces
      properties:
        namespaces[c]: "http://acme.com/cheese"
- route:
    from:
      uri: "file:inbox"
      steps:
        - split:
            expression:
              xtokenize:
                expression: "//c:order"
                namespacesRef: "myNamespaces"
            steps:
              - to: "mock:result"

Each prefix is configured as a namespaces[prefix] property on the bean, with the namespace URI as the value.

If the expression declares namespaces inline as well, then the inline namespaces win and namespacesRef is ignored.

Example

Suppose the input XML contains multiple orders:

<?xml version="1.0" encoding="UTF-8"?>
<orders xmlns="urn:shop">
    <order>
        <id>1001</id>
        <customer>John</customer>
    </order>
    <order>
        <id>1002</id>
        <customer>Jane</customer>
    </order>
</orders>

The XML Tokenize language can be used with the Split EIP to split the document into one message for each order element.

  • Java

  • XML

  • YAML

var ns = new org.apache.camel.support.builder.Namespaces("shop", "urn:shop");

from("direct:start")
  .split()
    .xtokenize("//shop:order", 'i', ns)
      .streaming()
    .to("mock:order");
<route>
    <from uri="direct:start"/>
    <split streaming="true">
        <xtokenize>//shop:order
            <namespace key="shop" value="urn:shop"/>
        </xtokenize>
        <to uri="mock:order"/>
    </split>
</route>
- route:
    from:
      uri: 'direct:start'
      steps:
        - split:
            streaming: 'true'
            expression:
              xtokenize:
                expression: '//shop:order'
                namespace:
                  - key: shop
                    value: 'urn:shop'
            steps:
              - to:
                  uri: 'mock:order'

The Split EIP produces two messages. The body of the first message is:

Output message 1
<order xmlns="urn:shop">
    <id>1001</id>
    <customer>John</customer>
</order>

The body of the second message is:

Output message 2
<order xmlns="urn:shop">
    <id>1002</id>
    <customer>Jane</customer>
</order>

The shop namespace is mapped to urn:shop, allowing the XPath expression //shop:order to identify the namespaced order elements.

See the Split EIP for more examples.