You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by zh...@apache.org on 2023/08/17 02:04:08 UTC

[camel-quarkus] branch main updated: Fix #5139 to expand xslt-saxon test coverage (#5173)

This is an automated email from the ASF dual-hosted git repository.

zhfeng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new 63433e39f1 Fix #5139 to expand xslt-saxon test coverage (#5173)
63433e39f1 is described below

commit 63433e39f1cec0b19fe3b311639acc16f8b70a93
Author: Zheng Feng <zh...@gmail.com>
AuthorDate: Thu Aug 17 10:04:03 2023 +0800

    Fix #5139 to expand xslt-saxon test coverage (#5173)
---
 extensions/xslt-saxon/deployment/pom.xml           |  2 +-
 extensions/xslt-saxon/runtime/pom.xml              |  2 +-
 .../xml/native/classpath/pom.xml                   |  4 +
 .../quarkus/component/xml/it/XsltResource.java     | 70 ++++++++--------
 .../quarkus/component/xml/it/XsltRouteBuilder.java |  9 +++
 .../resources/xslt/saxon-extension-function.xsl    | 30 ++++---
 .../camel/quarkus/component/xml/it/XsltTest.java   | 69 +++++++++++++---
 integration-tests-support/xslt-support/pom.xml     |  7 ++
 .../test/support/xslt/MyExtensionFunction1.java    | 89 +++++++++++++++++++++
 .../test/support/xslt/MyExtensionFunction2.java    | 92 ++++++++++++++++++++++
 integration-tests/xml-grouped/pom.xml              | 17 ++++
 11 files changed, 334 insertions(+), 57 deletions(-)

diff --git a/extensions/xslt-saxon/deployment/pom.xml b/extensions/xslt-saxon/deployment/pom.xml
index bdd784e498..e1b718e3cd 100644
--- a/extensions/xslt-saxon/deployment/pom.xml
+++ b/extensions/xslt-saxon/deployment/pom.xml
@@ -32,7 +32,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-core-deployment</artifactId>
+            <artifactId>camel-quarkus-xslt-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
diff --git a/extensions/xslt-saxon/runtime/pom.xml b/extensions/xslt-saxon/runtime/pom.xml
index a708e601be..cd3638cb56 100644
--- a/extensions/xslt-saxon/runtime/pom.xml
+++ b/extensions/xslt-saxon/runtime/pom.xml
@@ -38,7 +38,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-core</artifactId>
+            <artifactId>camel-quarkus-xslt</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
diff --git a/integration-test-groups/xml/native/classpath/pom.xml b/integration-test-groups/xml/native/classpath/pom.xml
index 32a604f90d..657f69f624 100644
--- a/integration-test-groups/xml/native/classpath/pom.xml
+++ b/integration-test-groups/xml/native/classpath/pom.xml
@@ -35,6 +35,10 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-xslt</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-xslt-saxon</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-xpath</artifactId>
diff --git a/integration-test-groups/xml/native/classpath/src/main/java/org/apache/camel/quarkus/component/xml/it/XsltResource.java b/integration-test-groups/xml/native/classpath/src/main/java/org/apache/camel/quarkus/component/xml/it/XsltResource.java
index a8187af8f4..db0473e193 100644
--- a/integration-test-groups/xml/native/classpath/src/main/java/org/apache/camel/quarkus/component/xml/it/XsltResource.java
+++ b/integration-test-groups/xml/native/classpath/src/main/java/org/apache/camel/quarkus/component/xml/it/XsltResource.java
@@ -22,17 +22,16 @@ import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
 import jakarta.ws.rs.Consumes;
 import jakarta.ws.rs.DefaultValue;
-import jakarta.ws.rs.GET;
 import jakarta.ws.rs.POST;
 import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
 import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.QueryParam;
 import jakarta.ws.rs.core.MediaType;
-import org.apache.camel.CamelContext;
+import net.sf.saxon.trans.XPathException;
 import org.apache.camel.ConsumerTemplate;
 import org.apache.camel.Exchange;
 import org.apache.camel.ProducerTemplate;
-import org.apache.camel.component.mock.MockEndpoint;
 import org.jboss.logging.Logger;
 
 @Path("/xml")
@@ -47,34 +46,45 @@ public class XsltResource {
     @Inject
     ConsumerTemplate consumerTemplate;
 
-    @Inject
-    CamelContext camelContext;
+    @Path("/stax")
+    @POST
+    @Produces(MediaType.TEXT_PLAIN)
+    public String stax(String body) {
+        return producerTemplate.requestBody("xslt-saxon:xslt/classpath-transform.xsl?allowStAX=true", body, String.class);
+    }
 
-    @Path("/xslt")
+    @Path("/{component}")
     @POST
     @Produces(MediaType.TEXT_PLAIN)
-    public String classpath(@QueryParam("output") @DefaultValue("string") String output, String body) {
+    public String classpath(@PathParam("component") String component,
+            @QueryParam("output") @DefaultValue("string") String output, String body) {
         if (output.equals("file")) {
-            return producerTemplate.requestBodyAndHeader("xslt:xslt/classpath-transform.xsl?output=file",
+            return producerTemplate.requestBodyAndHeader(component + ":xslt/classpath-transform.xsl?output=file",
                     body, Exchange.XSLT_FILE_NAME, "target/xsltme.xml", String.class);
         }
-        return producerTemplate.requestBody("xslt:xslt/classpath-transform.xsl?output=" + output, body, String.class);
+        return producerTemplate.requestBody(component + ":xslt/classpath-transform.xsl?output=" + output, body, String.class);
     }
 
-    @Path("/xslt_include")
+    @Path("/{component}/include")
     @POST
     @Produces(MediaType.TEXT_PLAIN)
-    public String xsltInclude(String body) {
-        return producerTemplate.requestBody("xslt:xslt/include.xsl", body, String.class);
+    public String xsltInclude(@PathParam("component") String component, String body) {
+        return producerTemplate.requestBody(component + ":xslt/include.xsl", body, String.class);
     }
 
-    @Path("/xslt_terminate")
+    @Path("/{component}/terminate")
     @POST
     @Produces(MediaType.TEXT_PLAIN)
-    public String xsltTerminate(String body) {
-        Exchange out = producerTemplate.request("xslt:xslt/terminate.xsl", exchange -> exchange.getIn().setBody(body));
-        Exception warning = out.getProperty(Exchange.XSLT_WARNING, Exception.class);
-        return warning.getMessage();
+    public String xsltTerminate(@PathParam("component") String component, String body) throws Exception {
+        Exchange out = producerTemplate.request(component + ":xslt/terminate.xsl", exchange -> exchange.getIn().setBody(body));
+        if (component.equals("xslt")) {
+            Exception warning = out.getProperty(Exchange.XSLT_WARNING, Exception.class);
+            return warning.getMessage();
+        } else if (component.equals("xslt-saxon")) {
+            Exception error = out.getProperty(Exchange.XSLT_FATAL_ERROR, Exception.class);
+            return ((XPathException) error).getErrorObject().head().getStringValue();
+        }
+        return "";
     }
 
     @Path("/xslt-extension-function")
@@ -84,28 +94,22 @@ public class XsltResource {
         return producerTemplate.requestBody("xslt:xslt/extension-function.xsl", body, String.class);
     }
 
-    @Path("/xslt-custom-uri-resolver")
+    @Path("/xslt-saxon-extension-function")
     @POST
     @Produces(MediaType.TEXT_PLAIN)
-    public String customURIResolver(String body) {
-        return producerTemplate.requestBody("xslt:xslt/include_not_existing_resource.xsl?uriResolver=#customURIResolver", body,
+    public String saxonExtensionFunction(String body) {
+        return producerTemplate.requestBody(
+                "xslt-saxon:xslt/saxon-extension-function.xsl?saxonExtensionFunctions=#function1,#function2", body,
                 String.class);
     }
 
-    @Path("/aggregate")
-    @GET
+    @Path("/{component}/custom-uri-resolver")
+    @POST
     @Produces(MediaType.TEXT_PLAIN)
-    public String aggregate() throws Exception {
-        MockEndpoint mock = camelContext.getEndpoint("mock:transformed", MockEndpoint.class);
-        mock.expectedMessageCount(1);
-
-        producerTemplate.sendBody("direct:aggregate", "<item>A</item>");
-        producerTemplate.sendBody("direct:aggregate", "<item>B</item>");
-        producerTemplate.sendBody("direct:aggregate", "<item>C</item>");
-
-        mock.assertIsSatisfied();
-        return mock.getExchanges().get(0).getIn().getBody(String.class);
-
+    public String customURIResolver(@PathParam("component") String component, String body) {
+        return producerTemplate.requestBody(
+                component + ":xslt/include_not_existing_resource.xsl?uriResolver=#customURIResolver", body,
+                String.class);
     }
 
     @Path("/html-transform")
diff --git a/integration-test-groups/xml/native/classpath/src/main/java/org/apache/camel/quarkus/component/xml/it/XsltRouteBuilder.java b/integration-test-groups/xml/native/classpath/src/main/java/org/apache/camel/quarkus/component/xml/it/XsltRouteBuilder.java
index 6ac82e302f..eb2533f907 100644
--- a/integration-test-groups/xml/native/classpath/src/main/java/org/apache/camel/quarkus/component/xml/it/XsltRouteBuilder.java
+++ b/integration-test-groups/xml/native/classpath/src/main/java/org/apache/camel/quarkus/component/xml/it/XsltRouteBuilder.java
@@ -18,7 +18,10 @@ package org.apache.camel.quarkus.component.xml.it;
 
 import org.w3c.dom.Document;
 
+import org.apache.camel.BindToRegistry;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.support.xslt.MyExtensionFunction1;
+import org.apache.camel.quarkus.test.support.xslt.MyExtensionFunction2;
 import org.apache.camel.support.builder.Namespaces;
 import org.apache.xpath.XPathAPI;
 
@@ -55,4 +58,10 @@ public class XsltRouteBuilder extends RouteBuilder {
                 .to("seda:xtokenize-result");
 
     }
+
+    @BindToRegistry
+    private MyExtensionFunction1 function1 = new MyExtensionFunction1();
+
+    @BindToRegistry
+    private MyExtensionFunction2 function2 = new MyExtensionFunction2();
 }
diff --git a/integration-tests-support/xslt-support/pom.xml b/integration-test-groups/xml/native/classpath/src/main/resources/xslt/saxon-extension-function.xsl
similarity index 57%
copy from integration-tests-support/xslt-support/pom.xml
copy to integration-test-groups/xml/native/classpath/src/main/resources/xslt/saxon-extension-function.xsl
index 5d6766047e..1793b2b62b 100644
--- a/integration-tests-support/xslt-support/pom.xml
+++ b/integration-test-groups/xml/native/classpath/src/main/resources/xslt/saxon-extension-function.xsl
@@ -17,15 +17,23 @@
     limitations under the License.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-integration-tests-support</artifactId>
-        <version>3.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
+<xsl:stylesheet version="2.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:func="http://mytest/" 
+    exclude-result-prefixes="func">
 
-    <artifactId>camel-quarkus-integration-tests-support-xslt</artifactId>
-    <name>Camel Quarkus :: Integration Tests :: Support :: XSLT</name>
-</project>
+	<xsl:output method="xml" encoding="UTF-8" indent="no" />
+
+	<xsl:template match="/">
+		<Test1>
+            <xsl:value-of select="func:myExtensionFunction1(1, 2)"/>
+        </Test1>
+        <Test2>
+            <xsl:value-of select="func:myExtensionFunction2('abc', 'cde')"/>
+        </Test2>
+        <Test3>
+            <xsl:value-of select="func:myExtensionFunction2('xyz')"/>
+        </Test3>
+	</xsl:template>
+
+</xsl:stylesheet>
diff --git a/integration-test-groups/xml/native/classpath/src/test/java/org/apache/camel/quarkus/component/xml/it/XsltTest.java b/integration-test-groups/xml/native/classpath/src/test/java/org/apache/camel/quarkus/component/xml/it/XsltTest.java
index a8852cb855..231c90c779 100644
--- a/integration-test-groups/xml/native/classpath/src/test/java/org/apache/camel/quarkus/component/xml/it/XsltTest.java
+++ b/integration-test-groups/xml/native/classpath/src/test/java/org/apache/camel/quarkus/component/xml/it/XsltTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.quarkus.component.xml.it;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.util.stream.Stream;
 
 import io.quarkus.test.junit.DisabledOnIntegrationTest;
 import io.quarkus.test.junit.QuarkusTest;
@@ -28,6 +29,8 @@ import org.apache.commons.io.IOUtils;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.jupiter.params.provider.ValueSource;
 
 import static org.hamcrest.Matchers.is;
@@ -36,12 +39,24 @@ import static org.hamcrest.Matchers.is;
 public class XsltTest {
     private static final String BODY = "<mail><subject>Hey</subject><body>Hello world!</body></mail>";
 
+    private static Stream<Arguments> matrix() {
+        return Stream.of(
+                Arguments.of("xslt", "string"),
+                Arguments.of("xslt", "bytes"),
+                Arguments.of("xslt", "dom"),
+                Arguments.of("xslt", "file"),
+                Arguments.of("xslt-saxon", "string"),
+                Arguments.of("xslt-saxon", "bytes"),
+                Arguments.of("xslt-saxon", "dom"),
+                Arguments.of("xslt-saxon", "file"));
+    }
+
     @ParameterizedTest
-    @ValueSource(strings = { "string", "bytes", "dom", "file" })
-    public void xslt(String output) throws Exception {
+    @MethodSource("matrix")
+    public void xslt(String component, String output) throws Exception {
         final String actual = RestAssured.given()
                 .body(BODY)
-                .post("/xml/xslt?output=" + output)
+                .post("/xml/" + component + "?output=" + output)
                 .then()
                 .statusCode(200)
                 .extract().body().asString().trim().replaceAll(">\\s+<", "><");
@@ -64,6 +79,20 @@ public class XsltTest {
         }
     }
 
+    @Test
+    public void saxonStAX() {
+        final String actual = RestAssured.given()
+                .body(BODY)
+                .post("/xml/stax")
+                .then()
+                .statusCode(200)
+                .extract().body().asString().trim().replaceAll(">\\s+<", "><");
+
+        Assertions.assertEquals(
+                "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><classpath-xsl subject=\"Hey\"><cheese><mail><subject>Hey</subject><body>Hello world!</body></mail></cheese></classpath-xsl>",
+                actual);
+    }
+
     @Test
     public void xsltExtensionFunction() {
         final String actual = RestAssured.given()
@@ -79,10 +108,26 @@ public class XsltTest {
     }
 
     @Test
-    public void xsltCustomURIResolver() {
+    @DisabledOnIntegrationTest("xslt-saxon extension function does not be supported in native mode")
+    public void saxonExtensionFunction() {
         final String actual = RestAssured.given()
                 .body(BODY)
-                .post("/xml/xslt-custom-uri-resolver")
+                .post("/xml/xslt-saxon-extension-function")
+                .then()
+                .statusCode(200)
+                .extract().body().asString().trim().replaceAll(">\\s+<", "><");
+
+        Assertions.assertEquals(
+                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Test1>3</Test1><Test2>abccde</Test2><Test3>xyz</Test3>",
+                actual);
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "xslt", "xslt-saxon" })
+    public void xsltCustomURIResolver(String component) {
+        final String actual = RestAssured.given()
+                .body(BODY)
+                .post("/xml/" + component + "/custom-uri-resolver")
                 .then()
                 .statusCode(200)
                 .extract().body().asString().trim().replaceAll(">\\s+<", "><");
@@ -92,12 +137,13 @@ public class XsltTest {
                 actual);
     }
 
-    @Test
+    @ParameterizedTest
+    @ValueSource(strings = { "xslt", "xslt-saxon" })
     @DisabledOnIntegrationTest("Generating xslt templates dynamically does not be supported in native mode")
-    public void xsltInclude() {
+    public void xsltInclude(String component) {
         final String actual = RestAssured.given()
                 .body(BODY)
-                .post("/xml/xslt_include")
+                .post("/xml/" + component + "/include")
                 .then()
                 .statusCode(200)
                 .extract().body().asString().trim().replaceAll(">\\s+<", "><");
@@ -107,12 +153,13 @@ public class XsltTest {
                 actual);
     }
 
-    @Test
+    @ParameterizedTest
+    @ValueSource(strings = { "xslt", "xslt-saxon" })
     @DisabledOnIntegrationTest("forwarding xslt error and warn messages does not be supported in native mode")
-    public void xsltTerminate() {
+    public void xsltTerminate(String component) {
         RestAssured.given()
                 .body("<staff><programmer><name>Daisy Duck</name><dob></dob></programmer></staff>")
-                .post("/xml/xslt_terminate")
+                .post("/xml/" + component + "/terminate")
                 .then()
                 .statusCode(200)
                 .body(is("Error: DOB is an empty string!"));
diff --git a/integration-tests-support/xslt-support/pom.xml b/integration-tests-support/xslt-support/pom.xml
index 5d6766047e..ad072e704f 100644
--- a/integration-tests-support/xslt-support/pom.xml
+++ b/integration-tests-support/xslt-support/pom.xml
@@ -28,4 +28,11 @@
 
     <artifactId>camel-quarkus-integration-tests-support-xslt</artifactId>
     <name>Camel Quarkus :: Integration Tests :: Support :: XSLT</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-xslt-saxon</artifactId>
+        </dependency>
+    </dependencies>
 </project>
diff --git a/integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/MyExtensionFunction1.java b/integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/MyExtensionFunction1.java
new file mode 100644
index 0000000000..6deccb68ca
--- /dev/null
+++ b/integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/MyExtensionFunction1.java
@@ -0,0 +1,89 @@
+/*
+ * 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.quarkus.test.support.xslt;
+
+import net.sf.saxon.expr.XPathContext;
+import net.sf.saxon.lib.ExtensionFunctionCall;
+import net.sf.saxon.lib.ExtensionFunctionDefinition;
+import net.sf.saxon.om.Item;
+import net.sf.saxon.om.Sequence;
+import net.sf.saxon.om.SequenceTool;
+import net.sf.saxon.om.StructuredQName;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.tree.iter.SingletonIterator;
+import net.sf.saxon.value.Int64Value;
+import net.sf.saxon.value.SequenceType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MyExtensionFunction1 extends ExtensionFunctionDefinition {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final Logger LOG = LoggerFactory.getLogger(MyExtensionFunction1.class);
+
+    @Override
+    public StructuredQName getFunctionQName() {
+        return new StructuredQName("", "http://mytest/", "myExtensionFunction1");
+    }
+
+    @Override
+    public int getMinimumNumberOfArguments() {
+        return 2;
+    }
+
+    @Override
+    public int getMaximumNumberOfArguments() {
+        return 2;
+    }
+
+    @Override
+    public SequenceType[] getArgumentTypes() {
+        return new SequenceType[] { SequenceType.SINGLE_INTEGER, SequenceType.SINGLE_INTEGER };
+    }
+
+    @Override
+    public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
+        int resultCardinality = 1;
+        return SequenceType.makeSequenceType(SequenceType.SINGLE_INTEGER.getPrimaryType(), resultCardinality);
+    }
+
+    @Override
+    public ExtensionFunctionCall makeCallExpression() {
+        return new ExtensionFunctionCall() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public Sequence call(XPathContext xPathContext, Sequence[] arguments) throws XPathException {
+                // 1st argument (mandatory, index 0)
+                Int64Value arg1 = (Int64Value) arguments[0].iterate().next();
+                int arg1Int = arg1.getDecimalValue().toBigInteger().intValue();
+
+                // 2nd argument (mandatory, index 1)
+                Int64Value arg2 = (Int64Value) arguments[1].iterate().next();
+                int arg2Int = arg2.getDecimalValue().toBigInteger().intValue();
+
+                // Functionality goes here
+                int resultInt = arg1Int + arg2Int;
+
+                Item result = new Int64Value(resultInt);
+                return SequenceTool.toLazySequence(SingletonIterator.makeIterator(result));
+            }
+        };
+    }
+
+}
diff --git a/integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/MyExtensionFunction2.java b/integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/MyExtensionFunction2.java
new file mode 100644
index 0000000000..fd89d0e54b
--- /dev/null
+++ b/integration-tests-support/xslt-support/src/main/java/org/apache/camel/quarkus/test/support/xslt/MyExtensionFunction2.java
@@ -0,0 +1,92 @@
+/*
+ * 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.quarkus.test.support.xslt;
+
+import net.sf.saxon.expr.XPathContext;
+import net.sf.saxon.lib.ExtensionFunctionCall;
+import net.sf.saxon.lib.ExtensionFunctionDefinition;
+import net.sf.saxon.om.Item;
+import net.sf.saxon.om.Sequence;
+import net.sf.saxon.om.SequenceTool;
+import net.sf.saxon.om.StructuredQName;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.tree.iter.SingletonIterator;
+import net.sf.saxon.value.SequenceType;
+import net.sf.saxon.value.StringValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MyExtensionFunction2 extends ExtensionFunctionDefinition {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final Logger LOG = LoggerFactory.getLogger(MyExtensionFunction2.class);
+
+    @Override
+    public StructuredQName getFunctionQName() {
+        return new StructuredQName("", "http://mytest/", "myExtensionFunction2");
+    }
+
+    @Override
+    public int getMinimumNumberOfArguments() {
+        return 1;
+    }
+
+    @Override
+    public int getMaximumNumberOfArguments() {
+        return 2;
+    }
+
+    @Override
+    public SequenceType[] getArgumentTypes() {
+        return new SequenceType[] { SequenceType.SINGLE_STRING, SequenceType.OPTIONAL_STRING };
+    }
+
+    @Override
+    public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
+        int resultCardinality = 1;
+        return SequenceType.makeSequenceType(SequenceType.SINGLE_STRING.getPrimaryType(), resultCardinality);
+    }
+
+    @Override
+    public ExtensionFunctionCall makeCallExpression() {
+        return new ExtensionFunctionCall() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public Sequence call(XPathContext xPathContext, Sequence[] arguments) throws XPathException {
+                // 1st argument (mandatory, index 0)
+                StringValue arg1 = (StringValue) arguments[0].iterate().next();
+                String arg1Str = arg1.getStringValue();
+
+                // 2nd argument (optional, index 1)
+                String arg2Str = "";
+                if (arguments.length > 1) {
+                    StringValue arg2 = (StringValue) arguments[1].iterate().next();
+                    arg2Str = arg2.getStringValue();
+                }
+
+                // Functionality goes here
+                String resultStr = arg1Str + arg2Str;
+
+                Item result = new StringValue(resultStr);
+                return SequenceTool.toLazySequence(SingletonIterator.makeIterator(result));
+            }
+        };
+    }
+
+}
diff --git a/integration-tests/xml-grouped/pom.xml b/integration-tests/xml-grouped/pom.xml
index df6aa428bc..d98ef3bf0f 100644
--- a/integration-tests/xml-grouped/pom.xml
+++ b/integration-tests/xml-grouped/pom.xml
@@ -72,6 +72,10 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-xslt</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-xslt-saxon</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-junit5</artifactId>
@@ -241,6 +245,19 @@
                         </exclusion>
                     </exclusions>
                 </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-xslt-saxon-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
             </dependencies>
         </profile>
     </profiles>