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 56f44e3bc40 CAMEL-19889: camel-xslt - Add option 
allowTemplateFromHeader (#11515)
56f44e3bc40 is described below

commit 56f44e3bc4032360075fa9b55a24f44532777a93
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Sep 21 17:25:04 2023 +0200

    CAMEL-19889: camel-xslt - Add option allowTemplateFromHeader (#11515)
---
 .../org/apache/camel/catalog/components/xj.json    |  3 +-
 .../camel/catalog/components/xslt-saxon.json       |  5 +-
 .../org/apache/camel/catalog/components/xslt.json  |  5 +-
 .../org/apache/camel/component/xj/xj.json          |  3 +-
 .../camel/component/xslt/saxon/xslt-saxon.json     |  5 +-
 .../component/xslt/saxon/XsltSaxonEndpoint.java    | 17 +++++
 ...tTemplateFromHeaderOverrideEndpointUriTest.java | 89 ++++++++++++++++++++++
 .../org/apache/camel/component/xslt/xslt.json      |  5 +-
 .../apache/camel/component/xslt/XsltBuilder.java   |  2 +-
 .../apache/camel/component/xslt/XsltConstants.java |  5 +-
 .../apache/camel/component/xslt/XsltEndpoint.java  | 17 +++++
 ...tTemplateFromHeaderOverrideEndpointUriTest.java | 89 ++++++++++++++++++++++
 .../endpoint/dsl/XJEndpointBuilderFactory.java     | 17 ++++-
 .../endpoint/dsl/XsltEndpointBuilderFactory.java   | 17 ++++-
 .../dsl/XsltSaxonEndpointBuilderFactory.java       | 17 ++++-
 15 files changed, 278 insertions(+), 18 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json
index 63f432fb0c4..61667f9cfc7 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json
@@ -37,7 +37,8 @@
   },
   "headers": {
     "CamelXsltFileName": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xj.XJConstants#XSLT_FILE_NAME" },
-    "CamelXsltResourceUri": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to use instead of the 
endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" }
+    "CamelXsltResourceUri": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to load and use instead 
of the endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
+    "CamelXsltStylesheet": { "index": 2, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The template to use instead of the endpoint 
configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" }
   },
   "properties": {
     "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource 
Uri", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Path to the template. The 
following is supported by the default URIResolver. You can prefix with: 
classpath, file, http, ref, or bean. classpath, file and http loads the 
resource using these protocols (classpath i [...]
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json
index 4f4d2b3d515..b9b5afaa6e4 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json
@@ -36,8 +36,9 @@
     "uriResolverFactory": { "index": 11, "kind": "property", "displayName": 
"Uri Resolver Factory", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": 
"org.apache.camel.component.xslt.XsltUriResolverFactory", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a custom 
UriResolver which depends on a dynamic endpoint resource URI. Should not be 
used together with the option 'uriResolver'." }
   },
   "headers": {
-    "CamelXsltResourceUri": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to use instead of the 
endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
-    "CamelXsltFileName": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" }
+    "CamelXsltResourceUri": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to load and use instead 
of the endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
+    "CamelXsltStylesheet": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The template to use instead of the endpoint 
configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" },
+    "CamelXsltFileName": { "index": 2, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" }
   },
   "properties": {
     "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource 
Uri", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Path to the template. The 
following is supported by the default URIResolver. You can prefix with: 
classpath, file, http, ref, or bean. classpath, file and http loads the 
resource using these protocols (classpath i [...]
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt.json
index 45824578244..eefbbbe6b55 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt.json
@@ -32,8 +32,9 @@
     "uriResolverFactory": { "index": 7, "kind": "property", "displayName": 
"Uri Resolver Factory", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": 
"org.apache.camel.component.xslt.XsltUriResolverFactory", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a custom 
UriResolver which depends on a dynamic endpoint resource URI. Should not be 
used together with the option 'uriResolver'." }
   },
   "headers": {
-    "CamelXsltResourceUri": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to use instead of the 
endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
-    "CamelXsltFileName": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" }
+    "CamelXsltResourceUri": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to load and use instead 
of the endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
+    "CamelXsltStylesheet": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The template to use instead of the endpoint 
configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" },
+    "CamelXsltFileName": { "index": 2, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" }
   },
   "properties": {
     "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource 
Uri", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Path to the template. The 
following is supported by the default URIResolver. You can prefix with: 
classpath, file, http, ref, or bean. classpath, file and http loads the 
resource using these protocols (classpath i [...]
diff --git 
a/components/camel-xj/src/generated/resources/org/apache/camel/component/xj/xj.json
 
b/components/camel-xj/src/generated/resources/org/apache/camel/component/xj/xj.json
index 63f432fb0c4..61667f9cfc7 100644
--- 
a/components/camel-xj/src/generated/resources/org/apache/camel/component/xj/xj.json
+++ 
b/components/camel-xj/src/generated/resources/org/apache/camel/component/xj/xj.json
@@ -37,7 +37,8 @@
   },
   "headers": {
     "CamelXsltFileName": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xj.XJConstants#XSLT_FILE_NAME" },
-    "CamelXsltResourceUri": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to use instead of the 
endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" }
+    "CamelXsltResourceUri": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to load and use instead 
of the endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
+    "CamelXsltStylesheet": { "index": 2, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The template to use instead of the endpoint 
configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" }
   },
   "properties": {
     "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource 
Uri", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Path to the template. The 
following is supported by the default URIResolver. You can prefix with: 
classpath, file, http, ref, or bean. classpath, file and http loads the 
resource using these protocols (classpath i [...]
diff --git 
a/components/camel-xslt-saxon/src/generated/resources/org/apache/camel/component/xslt/saxon/xslt-saxon.json
 
b/components/camel-xslt-saxon/src/generated/resources/org/apache/camel/component/xslt/saxon/xslt-saxon.json
index 4f4d2b3d515..b9b5afaa6e4 100644
--- 
a/components/camel-xslt-saxon/src/generated/resources/org/apache/camel/component/xslt/saxon/xslt-saxon.json
+++ 
b/components/camel-xslt-saxon/src/generated/resources/org/apache/camel/component/xslt/saxon/xslt-saxon.json
@@ -36,8 +36,9 @@
     "uriResolverFactory": { "index": 11, "kind": "property", "displayName": 
"Uri Resolver Factory", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": 
"org.apache.camel.component.xslt.XsltUriResolverFactory", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a custom 
UriResolver which depends on a dynamic endpoint resource URI. Should not be 
used together with the option 'uriResolver'." }
   },
   "headers": {
-    "CamelXsltResourceUri": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to use instead of the 
endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
-    "CamelXsltFileName": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" }
+    "CamelXsltResourceUri": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to load and use instead 
of the endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
+    "CamelXsltStylesheet": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The template to use instead of the endpoint 
configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" },
+    "CamelXsltFileName": { "index": 2, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" }
   },
   "properties": {
     "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource 
Uri", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Path to the template. The 
following is supported by the default URIResolver. You can prefix with: 
classpath, file, http, ref, or bean. classpath, file and http loads the 
resource using these protocols (classpath i [...]
diff --git 
a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java
 
b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java
index 9b22ac73280..eced83dc47d 100644
--- 
a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java
+++ 
b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.xslt.saxon;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.HashMap;
@@ -27,6 +28,7 @@ import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
 
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -38,6 +40,7 @@ import net.sf.saxon.TransformerFactoryImpl;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Category;
 import org.apache.camel.Component;
+import org.apache.camel.Exchange;
 import org.apache.camel.api.management.ManagedAttribute;
 import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.component.xslt.XsltBuilder;
@@ -248,6 +251,20 @@ public class XsltSaxonEndpoint extends XsltEndpoint {
         return xslt;
     }
 
+    @Override
+    protected XsltBuilder createBuilderForCustomStylesheet(String template, 
Exchange exchange) throws Exception {
+        InputStream is = 
getCamelContext().getTypeConverter().mandatoryConvertTo(InputStream.class, 
exchange, template);
+        XsltBuilder builder = createXsltBuilder();
+        Source source = new StreamSource(is);
+        if (this.saxonReaderProperties != null) {
+            //for Saxon we need to create XMLReader for the coming source
+            //so that the features configuration can take effect
+            source = createReaderForSource(source);
+        }
+        builder.setTransformerSource(source);
+        return builder;
+    }
+
     /**
      * Loads the resource.
      *
diff --git 
a/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/XsltTemplateFromHeaderOverrideEndpointUriTest.java
 
b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/XsltTemplateFromHeaderOverrideEndpointUriTest.java
new file mode 100644
index 00000000000..e53f4458b49
--- /dev/null
+++ 
b/components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/XsltTemplateFromHeaderOverrideEndpointUriTest.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.component.xslt;
+
+import java.util.List;
+
+import org.w3c.dom.Document;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxp.XmlConverter;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class XsltTemplateFromHeaderOverrideEndpointUriTest extends 
CamelTestSupport {
+
+    @Test
+    public void testSendStringMessage() throws Exception {
+        
sendMessageAndHaveItTransformed("<mail><subject>Hey</subject><body>Hello 
world!</body></mail>");
+    }
+
+    @Test
+    public void testSendBytesMessage() throws Exception {
+        
sendMessageAndHaveItTransformed("<mail><subject>Hey</subject><body>Hello 
world!</body></mail>".getBytes());
+    }
+
+    @Test
+    public void testSendDomMessage() throws Exception {
+        XmlConverter converter = new XmlConverter();
+        Document body = 
converter.toDOMDocument("<mail><subject>Hey</subject><body>Hello 
world!</body></mail>", null);
+        sendMessageAndHaveItTransformed(body);
+    }
+
+    private void sendMessageAndHaveItTransformed(Object body) throws Exception 
{
+        String sheet = 
IOHelper.loadText(XsltTemplateFromHeaderOverrideEndpointUriTest.class
+                
.getResourceAsStream("/org/apache/camel/component/xslt/transform.xsl"));
+        Assertions.assertNotNull(sheet);
+
+        MockEndpoint endpoint = getMockEndpoint("mock:result");
+        endpoint.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("direct:start", body, 
XsltConstants.XSLT_STYLESHEET, sheet);
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        List<Exchange> list = endpoint.getReceivedExchanges();
+        Exchange exchange = list.get(0);
+        String xml = exchange.getIn().getBody(String.class);
+
+        assertNotNull(xml, "The transformed XML should not be null");
+        assertTrue(xml.contains("transformed"));
+        // the cheese tag is in the transform.xsl
+        assertTrue(xml.contains("cheese"));
+        assertTrue(xml.contains("<subject>Hey</subject>"));
+        assertTrue(xml.contains("<body>Hello world!</body>"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                
from("direct:start").to("xslt-saxon:dummy.xsl?contentCache=false&allowTemplateFromHeader=true").multicast()
+                        .to("mock:result");
+            }
+        };
+    }
+
+}
diff --git 
a/components/camel-xslt/src/generated/resources/org/apache/camel/component/xslt/xslt.json
 
b/components/camel-xslt/src/generated/resources/org/apache/camel/component/xslt/xslt.json
index 45824578244..eefbbbe6b55 100644
--- 
a/components/camel-xslt/src/generated/resources/org/apache/camel/component/xslt/xslt.json
+++ 
b/components/camel-xslt/src/generated/resources/org/apache/camel/component/xslt/xslt.json
@@ -32,8 +32,9 @@
     "uriResolverFactory": { "index": 7, "kind": "property", "displayName": 
"Uri Resolver Factory", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": 
"org.apache.camel.component.xslt.XsltUriResolverFactory", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a custom 
UriResolver which depends on a dynamic endpoint resource URI. Should not be 
used together with the option 'uriResolver'." }
   },
   "headers": {
-    "CamelXsltResourceUri": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to use instead of the 
endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
-    "CamelXsltFileName": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" }
+    "CamelXsltResourceUri": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "A URI for the template resource to load and use instead 
of the endpoint configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" },
+    "CamelXsltStylesheet": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The template to use instead of the endpoint 
configured.", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" },
+    "CamelXsltFileName": { "index": 2, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The XSLT file name", "constantName": 
"org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" }
   },
   "properties": {
     "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource 
Uri", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Path to the template. The 
following is supported by the default URIResolver. You can prefix with: 
classpath, file, http, ref, or bean. classpath, file and http loads the 
resource using these protocols (classpath i [...]
diff --git 
a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java
 
b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java
index 9bbf8036427..4b0195b85c7 100644
--- 
a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java
+++ 
b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java
@@ -125,7 +125,7 @@ public class XsltBuilder implements Processor {
             resultHandler.setBody(out);
         } finally {
             releaseTransformer(transformer);
-            // IOHelper can handle if is is null
+            // IOHelper can handle if null
             IOHelper.close(is);
         }
     }
diff --git 
a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltConstants.java
 
b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltConstants.java
index fd99a048460..a48d523a9d7 100644
--- 
a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltConstants.java
+++ 
b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltConstants.java
@@ -21,8 +21,11 @@ import org.apache.camel.spi.Metadata;
 
 public final class XsltConstants {
 
-    @Metadata(description = "A URI for the template resource to use instead of 
the endpoint configured.", javaType = "String")
+    @Metadata(description = "A URI for the template resource to load and use 
instead of the endpoint configured.",
+              javaType = "String")
     public static final String XSLT_RESOURCE_URI = "CamelXsltResourceUri";
+    @Metadata(description = "The template to use instead of the endpoint 
configured. ", javaType = "String")
+    public static final String XSLT_STYLESHEET = "CamelXsltStylesheet";
     @Metadata(description = "The XSLT file name", javaType = "String")
     public static final String XSLT_FILE_NAME = Exchange.XSLT_FILE_NAME;
 
diff --git 
a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
 
b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
index 28f14f1077e..e114622a9d1 100644
--- 
a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
+++ 
b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.xslt;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -25,6 +26,7 @@ import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.URIResolver;
+import javax.xml.transform.stream.StreamSource;
 
 import org.xml.sax.EntityResolver;
 
@@ -127,6 +129,14 @@ public class XsltEndpoint extends ProcessorEndpoint {
                 newEndpoint.onExchange(exchange);
                 return;
             }
+            String template = 
exchange.getIn().getHeader(XsltConstants.XSLT_STYLESHEET, String.class);
+            if (template != null) {
+                // need to create a new builder that uses this template as 
source
+                LOG.trace("Using XSLT stylesheet from header: {}", 
XsltConstants.XSLT_STYLESHEET);
+                XsltBuilder builder = 
createBuilderForCustomStylesheet(template, exchange);
+                builder.process(exchange);
+                return;
+            }
         }
         if (!contentCache || cacheCleared) {
             loadResource(resourceUri, xslt);
@@ -134,6 +144,13 @@ public class XsltEndpoint extends ProcessorEndpoint {
         super.onExchange(exchange);
     }
 
+    protected XsltBuilder createBuilderForCustomStylesheet(String template, 
Exchange exchange) throws Exception {
+        InputStream is = 
getCamelContext().getTypeConverter().mandatoryConvertTo(InputStream.class, 
exchange, template);
+        XsltBuilder builder = createXsltBuilder();
+        builder.setTransformerSource(new StreamSource(is));
+        return builder;
+    }
+
     @ManagedAttribute(description = "Whether to allow to use resource template 
from header or not (default false).")
     public boolean isAllowTemplateFromHeader() {
         return allowTemplateFromHeader;
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/xslt/XsltTemplateFromHeaderOverrideEndpointUriTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/xslt/XsltTemplateFromHeaderOverrideEndpointUriTest.java
new file mode 100644
index 00000000000..039566298e9
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/xslt/XsltTemplateFromHeaderOverrideEndpointUriTest.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.component.xslt;
+
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.util.IOHelper;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class XsltTemplateFromHeaderOverrideEndpointUriTest extends 
ContextTestSupport {
+
+    @Test
+    public void testSendMessageAndHaveItTransformed() throws Exception {
+        MockEndpoint endpoint = getMockEndpoint("mock:result");
+        endpoint.expectedMessageCount(1);
+
+        String sheet = 
IOHelper.loadText(XsltTemplateFromHeaderOverrideEndpointUriTest.class
+                
.getResourceAsStream("/org/apache/camel/component/xslt/transform_to_foo.xsl"));
+        Assertions.assertNotNull(sheet);
+
+        template.sendBodyAndHeader("direct:start",
+                "<mail><subject>Hey</subject><body>Hello world!</body></mail>",
+                XsltConstants.XSLT_STYLESHEET, sheet);
+
+        assertMockEndpointsSatisfied();
+
+        List<Exchange> list = endpoint.getReceivedExchanges();
+        Exchange exchange = list.get(0);
+        String xml = exchange.getIn().getBody(String.class);
+
+        assertNotNull("The transformed XML should not be null", xml);
+        assertTrue(xml.contains("transformed"));
+        // the foo tag is in the transform_to_foo.xsl which is what we want. 
If this didn't
+        // work then transform.xsl would be used and we'd have a cheese element
+        assertTrue(xml.contains("foo"));
+        assertTrue(xml.contains("<subject>Hey</subject>"));
+        assertTrue(xml.contains("<body>Hello world!</body>"));
+
+        TestBean bean = context.getRegistry().lookupByNameAndType("testBean", 
TestBean.class);
+        assertNotNull(bean);
+        assertEquals("Hey", bean.getSubject());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        
.to("xslt:dummy.xsl?contentCache=false&allowTemplateFromHeader=true")
+                        .multicast()
+                        .bean("testBean")
+                        .to("mock:result");
+            }
+        };
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        context.getRegistry().bind("testBean", new TestBean());
+        return context;
+    }
+
+}
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java
index c335d16c138..8bd840334ea 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java
@@ -835,8 +835,8 @@ public interface XJEndpointBuilderFactory {
         }
 
         /**
-         * A URI for the template resource to use instead of the endpoint
-         * configured.
+         * A URI for the template resource to load and use instead of the
+         * endpoint configured.
          * 
          * The option is a: {@code String} type.
          * 
@@ -847,6 +847,19 @@ public interface XJEndpointBuilderFactory {
         public String xsltResourceUri() {
             return "XsltResourceUri";
         }
+
+        /**
+         * The template to use instead of the endpoint configured.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code XsltStylesheet}.
+         */
+        public String xsltStylesheet() {
+            return "XsltStylesheet";
+        }
     }
     static XJEndpointBuilder endpointBuilder(String componentName, String 
path) {
         class XJEndpointBuilderImpl extends AbstractEndpointBuilder implements 
XJEndpointBuilder, AdvancedXJEndpointBuilder {
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltEndpointBuilderFactory.java
index 30a150b418a..96e13a2cd5a 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltEndpointBuilderFactory.java
@@ -664,8 +664,8 @@ public interface XsltEndpointBuilderFactory {
         private static final XsltHeaderNameBuilder INSTANCE = new 
XsltHeaderNameBuilder();
 
         /**
-         * A URI for the template resource to use instead of the endpoint
-         * configured.
+         * A URI for the template resource to load and use instead of the
+         * endpoint configured.
          * 
          * The option is a: {@code String} type.
          * 
@@ -677,6 +677,19 @@ public interface XsltEndpointBuilderFactory {
             return "XsltResourceUri";
         }
 
+        /**
+         * The template to use instead of the endpoint configured.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code XsltStylesheet}.
+         */
+        public String xsltStylesheet() {
+            return "XsltStylesheet";
+        }
+
         /**
          * The XSLT file name.
          * 
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltSaxonEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltSaxonEndpointBuilderFactory.java
index 3bededbf9cd..f15cdc981d1 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltSaxonEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/XsltSaxonEndpointBuilderFactory.java
@@ -796,8 +796,8 @@ public interface XsltSaxonEndpointBuilderFactory {
         private static final XsltSaxonHeaderNameBuilder INSTANCE = new 
XsltSaxonHeaderNameBuilder();
 
         /**
-         * A URI for the template resource to use instead of the endpoint
-         * configured.
+         * A URI for the template resource to load and use instead of the
+         * endpoint configured.
          * 
          * The option is a: {@code String} type.
          * 
@@ -809,6 +809,19 @@ public interface XsltSaxonEndpointBuilderFactory {
             return "XsltResourceUri";
         }
 
+        /**
+         * The template to use instead of the endpoint configured.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code XsltStylesheet}.
+         */
+        public String xsltStylesheet() {
+            return "XsltStylesheet";
+        }
+
         /**
          * The XSLT file name.
          * 


Reply via email to