XPathPage edited by Claus IbsenXPathCamel supports XPath to allow an _expression_ or Predicate to be used in the DSL or Xml Configuration. For example you could use XPath to create an Predicate in a Message Filter or as an _expression_ for a Recipient List. from("queue:foo"). filter().xpath("//foo")). to("queue:bar")
Camel will resolve variables according to either:
Namespace givenIf the namespace is given then Camel is instructed exactly what to return. However when resolving either in or out Camel will try to resolve a header with the given local part first, and return it. If the local part has the value body then the body is returned instead. No namespace givenIf there is no namespace given then Camel resolves only based on the local part. Camel will try to resolve a variable in the following steps:
FunctionsCamel adds the following XPath functions that can be used to access the exchange:
Here's an example showing some of these functions in use. from("direct:start").choice() .when().xpath("in:header('foo') = 'bar'").to("mock:x") .when().xpath("in:body() = '<two/>'").to("mock:y") .otherwise().to("mock:z"); Using XML configurationIf you prefer to configure your routes in your Spring XML file then you can use XPath expressions as follows <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring" xmlns:foo="http://example.com/person"> <route> <from uri="activemq:MyQueue"/> <filter> <xpath>/foo:pers...@name='James']</xpath> <to uri="mqseries:SomeOtherQueue"/> </filter> </route> </camelContext> </beans> Notice how we can reuse the namespace prefixes, foo in this case, in the XPath _expression_ for easier namespace based XPath expressions! See also this discussion on the mailinglist about using your own namespaces with xpath Setting result typeThe XPath _expression_ will return a result type using native XML objects such as org.w3c.dom.NodeList. But many times you want a result type to be a String. To do this you have to instruct the XPath which result type to use. In Java DSL: xpath("/foo:person/@id", String.class) In Spring DSL you use the resultType attribute to provide a fully qualified classname: <xpath resultType="java.lang.String">/foo:person/@id</xpath> In @XPath:
@XPath(value = "concat('foo-',//order/name/)", resultType = String.class) String name)
Where we use the xpath function concat to prefix the order name with foo-. In this case we have to specify that we want a String as result type so the concat function works. ExamplesHere is a simple example using an XPath _expression_ as a predicate in a Message Filter from("direct:start"). filter().xpath("/pers...@name='James']"). to("mock:result"); If you have a standard set of namespaces you wish to work with and wish to share them across many different XPath expressions you can use the NamespaceBuilder as shown in this example // lets define the namespaces we'll need in our filters Namespaces ns = new Namespaces("c", "http://acme.com/cheese") .add("xsd", "http://www.w3.org/2001/XMLSchema"); // now lets create an xpath based Message Filter from("direct:start"). filter(ns.xpath("/c:pers...@name='James']")). to("mock:result"); In this sample we have a choice construct. The first choice evaulates if the message has a header key type that has the value Camel. from("direct:in").choice() // using $headerName is special notation in Camel to get the header key .when().xpath("$type = 'Camel'") .to("mock:camel") // here we test for the body name tag .when().xpath("//name = 'Kong'") .to("mock:donkey") .otherwise() .to("mock:other") .end(); And the spring XML equivalent of the route: <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct:in"/> <choice> <when> <xpath>$type = 'Camel'</xpath> <to uri="mock:camel"/> </when> <when> <xpath>//name = 'Kong'</xpath> <to uri="mock:donkey"/> </when> <otherwise> <to uri="mock:other"/> </otherwise> </choice> </route> </camelContext> XPath injectionYou can use Bean Integration to invoke a method on a bean and use various languages such as XPath to extract a value from the message and bind it to a method parameter. The default XPath annotation has SOAP and XML namespaces available. If you want to use your own namespace URIs in an XPath _expression_ you can use your own copy of the XPath annotation to create whatever namespace prefixes you want to use. import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.w3c.dom.NodeList; import org.apache.camel.component.bean.XPathAnnotationExpressionFactory; import org.apache.camel.language.LanguageAnnotation; import org.apache.camel.language.NamespacePrefix; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @LanguageAnnotation(language = "xpath", factory = XPathAnnotationExpressionFactory.class) public @interface MyXPath { String value(); // You can add the namespaces as the default value of the annotation NamespacePrefix[] namespaces() default { @NamespacePrefix(prefix = "n1", uri = "http://example.org/ns1"), @NamespacePrefix(prefix = "n2", uri = "http://example.org/ns2")}; Class<?> resultType() default NodeList.class; } i.e. cut and paste upper code to your own project in a different package and/or annotation name then add whatever namespace prefix/uris you want in scope when you use your annotation on a method parameter. Then when you use your annotation on a method parameter all the namespaces you want will be available for use in your XPath _expression_. NOTE this feature is supported from Camel 1.6.1. For example public class Foo { @MessageDriven(uri = "activemq:my.queue") public void doSomething(@Path("/foo/bar/text()") String correlationID, @Body String body) { // process the inbound message here } } Using XPathBuilder without an ExchangeAvailable as of Camel 2.3 You can now use the org.apache.camel.builder.XPathBuilder without the need for an Exchange. This comes handy if you want to use it as a helper to do custom xpath evaluations. It requires that you pass in a CamelContext since a lot of the moving parts inside the XPathBuilder requires access to the Camel Type Converter and hence why CamelContext is needed. For example you can do something like this: boolean matches = XPathBuilder.xpath("/foo/bar/@xyz").matches(context, "<foo><bar xyz='cheese'/></foo>")); This will match the given predicate. You can also evaluate for example as shown in the following three examples: String name = XPathBuilder.xpath("foo/bar").evaluate(context, "<foo><bar>cheese</bar></foo>", String.class); Integer number = XPathBuilder.xpath("foo/bar").evaluate(context, "<foo><bar>123</bar></foo>", Integer.class); Boolean bool = XPathBuilder.xpath("foo/bar").evaluate(context, "<foo><bar>true</bar></foo>", Boolean.class); DependenciesThe XPath language is part of camel-core.
Change Notification Preferences
View Online
|
View Change
|
Add Comment
|
- [CONF] Apache Camel > XPath confluence
- [CONF] Apache Camel > XPath confluence
- [CONF] Apache Camel > XPath confluence
- [CONF] Apache Camel > XPath confluence
- [CONF] Apache Camel > XPath confluence
- [CONF] Apache Camel > XPath confluence