Cameleer

XQuery language

The xquery language evaluates an XQuery expression (FLWOR, constructors, XPath) against an XML message and returns the result.

Name: xquery · Crate: cameleer-xml · Cargo feature: xml · Apache Camel: XQuery

When to use it

  • Compute a value from XML that XPath 1.0 cannot express easily: for ... order by ... return, string-join, sums over computed values.
  • Build a small XML fragment from an incoming document in a single expression.
  • Filter or route XML messages with an XQuery predicate.

For a query kept in a file and run as a step, use the xquery component.

Syntax

Cameleer has its own XQuery processor (Apache Camel uses Saxon). The body, or the input named by headerName/source, is parsed as the context document.

External variables are bound like camel-saxon does:

declarationvalue
declare variable $in.body external;the body
declare variable $in.headers.NAME external;header NAME
declare variable $NAME external;exchange property NAME, else header, else variable

A declared atomic type casts the value (as xs:integer); a node type (as element()) parses it as XML.

Result. By default (resultType DOM) the result is serialized as XML text, with atomic values separated by spaces. Predicates use the effective boolean value.

Syntax reference, tested

json
{"body": "<order id=\"42\"><customer>Ada</customer><item sku=\"A1\" qty=\"2\" price=\"9.50\"/><item sku=\"B2\" qty=\"1\" price=\"20\"/></order>",
 "headers": {"region": "eu"}}
expressionresult
/order/customer/text()Ada
for $i in //item return string($i/@sku)A1 B2
string-join(//item/@sku, ',')A1,B2
sum(for $i in //item return $i/@qty * $i/@price)39
<skus>{for $i in //item order by $i/@sku descending return <sku>{string($i/@sku)}</sku>}</skus><skus><sku>B2</sku><sku>A1</sku></skus>
declare variable $in.headers.region external; concat(/order/customer, '@', $in.headers.region)Ada@eu
expressionresult
count(//item) > 1true
some $i in //item satisfies $i/@price > 100false

Examples

Build a summary with FLWOR

yaml example: xquery-summary
- route:
    id: xquery-summary
    from:
      uri: direct:xquery-summary
      steps:
        - setBody:
            xquery:
              expression: >-
                declare variable $in.headers.currency external;
                <summary customer="{/order/customer}" currency="{$in.headers.currency}">{
                  for $i in //item
                  let $line := $i/@qty * $i/@price
                  order by $line descending
                  return <line sku="{$i/@sku}">{$line}</line>
                }</summary>
xml
<order><customer>Ada</customer><item sku="A1" qty="2" price="9.50"/><item sku="B2" qty="3" price="20"/></order>
xml
<summary customer="Ada" currency="EUR"><line sku="B2">60</line><line sku="A1">19</line></summary>

Filter with an XQuery predicate

yaml example: xquery-filter
- route:
    id: xquery-filter
    from:
      uri: direct:xquery-filter
      steps:
        - setHeader:
            name: big
            constant: "no"
        - filter:
            xquery: "sum(//item/@qty) >= 10"
            steps:
              - setHeader:
                  name: big
                  constant: "yes"
        - setBody:
            xquery:
              expression: "sum(//item/@qty)"
              resultType: Integer
        - setBody:
            simple: "qty=${body} big=${header.big}"
xml
<order><item qty="4"/><item qty="7"/></order>
text
qty=11 big=yes

Options

optiondefaultdescription
resultTypeDOMDOM (XML text), String (string values concatenated), List/NodeList (array), Node/Element (first item), Bytes, Integer/Long, Double, Boolean. Java class names are accepted.
namespace / namespaces(none)Prefix bindings, same syntax as the xpath language.
stripsAllWhiteSpacetrueDrop whitespace-only text nodes of the input, as Saxon does for Camel.
headerName(none)Evaluate this header instead of the body.
source(none)header:x, property:x, variable:x or body.

Rust DSL

rust
b.from("direct:xquery-rust")
    .set_body(cameleer_xml::xquery_component::xquery_expr("string-join(//item/@sku, ',')"));

Common questions

How do I pass a header into an XQuery?

Declare it: declare variable $in.headers.currency external; and use $in.headers.currency.

What is the difference between the xquery language and the xquery component?

The language evaluates an inline expression wherever an expression fits (setBody, filter, split...). The component runs a query file as a producer step: to: xquery:file:summary.xq.

Which XQuery version is supported?

The commonly used XQuery 1.0 features (FLWOR, constructors, quantified expressions, external variables) with XPath 2.0 functions; there is no Saxon, schema awareness or XQuery Update.

Found a problem?

If something on this page doesn't match what Cameleer does, or you hit a bug while building with it, please help fix it, whether you are a person or a coding agent: open an issue that describes what you saw, then fork the repository, fix it, add or update a test, run cargo test --workspace, and open a pull request. CONTRIBUTING.md explains the ground rules.

Edit this page on GitHub