This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 6985d372bba CAMEL-20151: camel-xpath - Add xpath as function to simple
for basic templating (#12194)
6985d372bba is described below
commit 6985d372bba15131672895d245f5ffa76336ddc2
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Nov 24 16:30:44 2023 +0100
CAMEL-20151: camel-xpath - Add xpath as function to simple for basic
templating (#12194)
---
.../camel-xpath/src/main/docs/xpath-language.adoc | 57 ++++++++++++++++++
.../modules/languages/pages/simple-language.adoc | 3 +
.../simple/ast/SimpleFunctionExpression.java | 9 +++
.../camel/language/SimpleXPathTransformTest.java | 69 ++++++++++++++++++++++
4 files changed, 138 insertions(+)
diff --git a/components/camel-xpath/src/main/docs/xpath-language.adoc
b/components/camel-xpath/src/main/docs/xpath-language.adoc
index da7706b8b94..43f736a571b 100644
--- a/components/camel-xpath/src/main/docs/xpath-language.adoc
+++ b/components/camel-xpath/src/main/docs/xpath-language.adoc
@@ -513,6 +513,63 @@ eg to refer to a file on the classpath you can do:
.setHeader("myHeader").xpath("resource:classpath:myxpath.txt", String.class)
----
+== Transforming a XML message
+
+For basic XML transformation where you have a fixed structure you can
represent with a combination of using
+Camel simple and XPath language as:
+
+Given this XML body
+
+[source,xml]
+----
+<order id="123">
+ <item>Brake</item>
+ <first>scott</first>
+ <last>jackson</last>
+ <address>
+ <co>sweden</co>
+ <zip>12345</zip>
+ </address>
+</order>
+----
+
+Which you want to transform to a smaller structure:
+
+[source,xml]
+----
+<user>
+ <rool>123</rool>
+ <country>sweden</country>
+ <fullname>scott</fullname>
+</user>
+----
+
+Then you can use simple as template and XPath to grab the content from the
message payload, as shown in the route snippet below:
+
+[source,java]
+----
+from("direct:start")
+ .transform().simple("""
+ <user>
+ <rool>${xpath(/order/@id)}</rool>
+ <country>${xpath(/order/address/co/text())}</country>
+ <fullname>${xpath(/order/first/text())}</fullname>
+ </user>""")
+ .to("mock:result");
+----
+
+Notice how we use `${xpath(exp}` syntax in the simple template to use xpath
that will be evaluated on the message body,
+to extract the content to be used in the output (see previous for output).
+
+Since the simple language can output anything you can also use this to output
in plain text or JSon etc.
+
+[source,java]
+----
+from("direct:start")
+ .transform().simple("The order ${xpath(/order/@id)} is being shipped
to ${xpath(/order/address/co/text())}")
+ .to("mock:result");
+----
+
== Dependencies
To use XPath in your camel routes you need to add the dependency on
diff --git
a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
index b2f43ee25c2..9d9452bb9b1 100644
---
a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
+++
b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
@@ -255,6 +255,9 @@ where the ID is _myGenerator_.
|jq(exp) | Object | When working with JSon data, then this allows to use the
JQ language
for example to extract data from the message body (in JSon format). This
requires having camel-jq JAR on the classpath.
+|xpath(exp) | Object | When working with XML data, then this allows to use the
XPath language
+for example to extract data from the message body (in XML format). This
requires having camel-xpath JAR on the classpath.
+
|=======================================================================
== OGNL expression support
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index edf10b84a0c..d0f93f30cce 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -462,6 +462,15 @@ public class SimpleFunctionExpression extends
LiteralExpression {
exp = StringHelper.removeQuotes(exp);
return ExpressionBuilder.languageExpression("jq", exp);
}
+ remainder = ifStartsWithReturnRemainder("xpath(", function);
+ if (remainder != null) {
+ String exp = StringHelper.beforeLast(remainder, ")");
+ if (exp == null) {
+ throw new SimpleParserException("Valid syntax: ${xpath(exp)}
was: " + function, token.getIndex());
+ }
+ exp = StringHelper.removeQuotes(exp);
+ return ExpressionBuilder.languageExpression("xpath", exp);
+ }
return null;
}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/SimpleXPathTransformTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/SimpleXPathTransformTest.java
new file mode 100644
index 00000000000..dbba17e0d76
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/SimpleXPathTransformTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+public class SimpleXPathTransformTest extends ContextTestSupport {
+
+ private static String EXPECTED = """
+ <user>
+ <rool>123</rool>
+ <country>sweden</country>
+ <fullname>scott</fullname>
+ </user>""";
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:start")
+ .transform().simple("""
+ <user>
+ <rool>${xpath(/order/@id)}</rool>
+
<country>${xpath(/order/address/co/text())}</country>
+
<fullname>${xpath(/order/first/text())}</fullname>
+ </user>""")
+ .to("mock:result");
+ }
+ };
+ }
+
+ @Test
+ public void testTransform() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived(EXPECTED);
+
+ template.sendBody("direct:start", """
+ <order id="123">
+ <item>Brake</item>
+ <first>scott</first>
+ <last>jackson</last>
+ <address>
+ <co>sweden</co>
+ <zip>12345</zip>
+ </address>
+ </order>
+ """);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+}