Added Xslt component docs to Gitbook
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/fd256485 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/fd256485 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/fd256485 Branch: refs/heads/master Commit: fd256485dc766a57f375f434f9c5d016e49425a8 Parents: 49b843f Author: Andrea Cosentino <[email protected]> Authored: Thu Jun 23 10:40:41 2016 +0200 Committer: Andrea Cosentino <[email protected]> Committed: Thu Jun 23 10:40:41 2016 +0200 ---------------------------------------------------------------------- camel-core/src/main/docs/xslt.adoc | 410 ++++++++++++++++++++++++++++++++ docs/user-manual/en/SUMMARY.md | 1 + 2 files changed, 411 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/fd256485/camel-core/src/main/docs/xslt.adoc ---------------------------------------------------------------------- diff --git a/camel-core/src/main/docs/xslt.adoc b/camel-core/src/main/docs/xslt.adoc new file mode 100644 index 0000000..8fb1e00 --- /dev/null +++ b/camel-core/src/main/docs/xslt.adoc @@ -0,0 +1,410 @@ +[[XSLT-XSLT]] +XSLT +~~~~ + +The *xslt:* component allows you to process a message using an +http://www.w3.org/TR/xslt[XSLT] template. This can be ideal when using +link:templating.html[Templating] to generate respopnses for requests. + +[[XSLT-URIformat]] +URI format +^^^^^^^^^^ + +[source,java] +--------------------------- +xslt:templateName[?options] +--------------------------- + +Where *templateName* is the classpath-local URI of the template to +invoke; or the complete URL of the remote template. Refer to the +http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/core/io/DefaultResourceLoader.html[Spring +Documentation for more detail of the URI syntax] + +You can append query options to the URI in the following format, +`?option=value&option=value&...` + +Here are some example URIs + +URI + +Description + +[source,java] +----------------------------- +xslt:com/acme/mytransform.xsl +----------------------------- + +refers to the file com/acme/mytransform.xsl on the classpath + +[source,java] +------------------------ +xslt:file:///foo/bar.xsl +------------------------ + +refers to the file /foo/bar.xsl + +[source,java] +----------------------------------- +xslt:http://acme.com/cheese/foo.xsl +----------------------------------- + +refers to the remote http resource + +Maven users will need to add the following dependency to their `pom.xml` +for this component when using *Camel 2.8* or older: + +[source,xml] +------------------------------------------------------------ +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-spring</artifactId> + <version>x.x.x</version> + <!-- use the same version as your Camel core version --> +</dependency> +------------------------------------------------------------ + +From Camel 2.9 onwards the link:xslt.html[XSLT] component is provided +directly in the camel-core. + +[[XSLT-Options]] +Options +^^^^^^^ + +// component options: START +// component options: END + +// endpoint options: START +// endpoint options: END + +[[XSLT-UsingXSLTendpoints]] +Using XSLT endpoints +^^^^^^^^^^^^^^^^^^^^ + +For example you could use something like + +[source,java] +-------------------------------------- +from("activemq:My.Queue"). + to("xslt:com/acme/mytransform.xsl"); +-------------------------------------- + +To use an XSLT template to formulate a response for a message for InOut +message exchanges (where there is a `JMSReplyTo` header). + +If you want to use InOnly and consume the message and send it to another +destination you could use the following route: + +[source,java] +-------------------------------------- +from("activemq:My.Queue"). + to("xslt:com/acme/mytransform.xsl"). + to("activemq:Another.Queue"); +-------------------------------------- + +[[XSLT-GettingParametersintotheXSLTtoworkwith]] +Getting Parameters into the XSLT to work with +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, all headers are added as parameters which are available in +the XSLT. + + To do this you will need to declare the parameter so it is then +_useable_. + +[source,xml] +------------------------------------------------------------------- +<setHeader headerName="myParam"><constant>42</constant></setHeader> +<to uri="xslt:MyTransform.xsl"/> +------------------------------------------------------------------- + +And the XSLT just needs to declare it at the top level for it to be +available: + +[source,xml] +------------------------------ +<xsl: ...... > + + <xsl:param name="myParam"/> + + <xsl:template ...> +------------------------------ + +[[XSLT-SpringXMLversions]] +Spring XML versions +^^^^^^^^^^^^^^^^^^^ + +To use the above examples in Spring XML you would use something like + +[source,xml] +----------------------------------------------------------------------- + <camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> + <route> + <from uri="activemq:My.Queue"/> + <to uri="xslt:org/apache/camel/spring/processor/example.xsl"/> + <to uri="activemq:Another.Queue"/> + </route> + </camelContext> +----------------------------------------------------------------------- + +There is a +http://svn.apache.org/repos/asf/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/XsltTest.java[test +case] along with +http://svn.apache.org/repos/asf/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/XsltTest-context.xml[its +Spring XML] if you want a concrete example. + +[[XSLT-Usingxsl:include]] +Using xsl:include +^^^^^^^^^^^^^^^^^ + +*Camel 2.2 or older* + + If you use xsl:include in your XSL files then in Camel 2.2 or older it +uses the default `javax.xml.transform.URIResolver` which means it can +only lookup files from file system, and its does that relative from the +JVM starting folder. + +For example this include: + +[source,xml] +---------------------------------------- +<xsl:include href="staff_template.xsl"/> +---------------------------------------- + +Will lookup the `staff_tempkalte.xsl` file from the starting folder +where the application was started. + +*Camel 2.3 or newer* + + Now Camel provides its own implementation of `URIResolver` which allows +Camel to load included files from the classpath and more intelligent +than before. + +For example this include: + +[source,xml] +---------------------------------------- +<xsl:include href="staff_template.xsl"/> +---------------------------------------- + +Will now be located relative from the starting endpoint, which for +example could be: + +[source,java] +---------------------------------------------------------------------- +.to("xslt:org/apache/camel/component/xslt/staff_include_relative.xsl") +---------------------------------------------------------------------- + +Which means Camel will locate the file in the *classpath* as +`org/apache/camel/component/xslt/staff_template.xsl`. + + This allows you to use xsl include and have xsl files located in the +same folder such as we do in the example +`org/apache/camel/component/xslt`. + +You can use the following two prefixes `classpath:` or `file:` to +instruct Camel to look either in classpath or file system. If you omit +the prefix then Camel uses the prefix from the endpoint configuration. +If that neither has one, then classpath is assumed. + +You can also refer back in the paths such as + +[source,java] +----------------------------------------------------- + <xsl:include href="../staff_other_template.xsl"/> +----------------------------------------------------- + +Which then will resolve the xsl file under `org/apache/camel/component`. + +[[XSLT-Usingxsl:includeanddefaultprefix]] +Using xsl:include and default prefix +++++++++++++++++++++++++++++++++++++ + +When using xsl:include such as: + +[source,xml] +---------------------------------------- +<xsl:include href="staff_template.xsl"/> +---------------------------------------- + +Then in Camel 2.10.3 and older, then Camel will use "classpath:" as the +default prefix, and load the resource from the classpath. This works for +most cases, but if you configure the starting resource to load from +file, + +[source,java] +---------------------------------------------------- +.to("xslt:file:etc/xslt/staff_include_relative.xsl") +---------------------------------------------------- + +.. then you would have to prefix all your includes with "file:" as well. + +[source,xml] +--------------------------------------------- +<xsl:include href="file:staff_template.xsl"/> +--------------------------------------------- + +From Camel 2.10.4 onwards we have made this easier as Camel will use the +prefix from the endpoint configuration as the default prefix. So from +Camel 2.10.4 onwards you can do: + +[source,xml] +---------------------------------------- +<xsl:include href="staff_template.xsl"/> +---------------------------------------- + +Which will load the staff_template.xsl resource from the file system, as +the endpoint was configured with "file:" as prefix. + + You can still though explicit configure a prefix, and then mix and +match. And have both file and classpath loading. But that would be +unusual, as most people either use file or classpath based resources. + +[[XSLT-UsingSaxonextensionfunctions]] +Using Saxon extension functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Since Saxon 9.2, writing extension functions has been supplemented by a +new mechanism, referred to +as http://www.saxonica.com/html/documentation/extensibility/integratedfunctions[integrated +extension functions] you can now easily use camel: + + + +- Java example: + +[source,java] +--------------------------------------------------------------------------------------------------------------------------------- +SimpleRegistry registry = new SimpleRegistry(); +registry.put("function1", new MyExtensionFunction1()); +registry.put("function2", new MyExtensionFunction2()); + +CamelContext context = new DefaultCamelContext(registry); +context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start") + .to("xslt:org/apache/camel/component/xslt/extensions/extensions.xslt?saxonExtensionFunctions=#function1,#function2"); + } +}); +--------------------------------------------------------------------------------------------------------------------------------- + + + +Spring example: + +[source,xml] +----------------------------------------------------------------------------------------------------------------------------- +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:extensions"/> + <to uri="xslt:org/apache/camel/component/xslt/extensions/extensions.xslt?saxonExtensionFunctions=#function1,#function2"/> + </route> +</camelContext> + + +<bean id="function1" class="org.apache.camel.component.xslt.extensions.MyExtensionFunction1"/> +<bean id="function2" class="org.apache.camel.component.xslt.extensions.MyExtensionFunction2"/> +----------------------------------------------------------------------------------------------------------------------------- + + + + + +[[XSLT-Dynamicstylesheets]] +Dynamic stylesheets +^^^^^^^^^^^^^^^^^^^ + +To provide a dynamic stylesheet at runtime you can define a dynamic URI. +See link:how-to-use-a-dynamic-uri-in-to.html[How to use a dynamic URI in +to()] for more information. + +*Available as of Camel 2.9 (removed in 2.11.4, 2.12.3 and 2.13.0)* + + Camel provides the `CamelXsltResourceUri` header which you can use to +define a stylesheet to use instead of what is configured on the endpoint +URI. This allows you to provide a dynamic stylesheet at runtime. + +[[XSLT-Accessingwarnings,errorsandfatalErrorsfromXSLTErrorListener]] +Accessing warnings, errors and fatalErrors from XSLT ErrorListener +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Available as of Camel 2.14* + +From Camel 2.14 onwards, any warning/error or fatalError is stored on +the current Exchange as a property with the +keys `Exchange.XSLT_ERROR`, `Exchange.XSLT_FATAL_ERROR`, +or `Exchange.XSLT_WARNING` which allows end users to get hold of any +errors happening during transformation. + +For example in the stylesheet below, we want to terminate if a staff has +an empty dob field. And to include a custom error message using +xsl:message. + +[source,java] +--------------------------------------------------------------------------------------- + <xsl:template match="/"> + <html> + <body> + <xsl:for-each select="staff/programmer"> + <p>Name: <xsl:value-of select="name"/><br /> + <xsl:if test="dob=''"> + <xsl:message terminate="yes">Error: DOB is an empty string!</xsl:message> + </xsl:if> + </p> + </xsl:for-each> + </body> + </html> + </xsl:template> +--------------------------------------------------------------------------------------- + +This information is not available on the Exchange stored as an Exception +that contains the message in the `getMessage()` method on the exception. +The exception is stored on the Exchange as a warning with the +key `Exchange.XSLT_WARNING.` + +[[XSLT-NotesonusingXSLTandJavaVersions]] +Notes on using XSLT and Java Versions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Here are some observations from Sameer, a Camel user, which he kindly +shared with us: + +________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ +In case anybody faces issues with the XSLT endpoint please review these +points. + +I was trying to use an xslt endpoint for a simple transformation from +one xml to another using a simple xsl. The output xml kept appearing +(after the xslt processor in the route) with outermost xml tag with no +content within. + +No explanations show up in the DEBUG logs. On the TRACE logs however I +did find some error/warning indicating that the XMLConverter bean could +no be initialized. + +After a few hours of cranking my mind, I had to do the following to get +it to work (thanks to some posts on the users forum that gave some +clue): + +\1. Use the transformerFactory option in the route +`("xslt:my-transformer.xsl?transformerFactory=tFactory")` with the +`tFactory` bean having bean defined in the spring context for +`class="org.apache.xalan.xsltc.trax.TransformerFactoryImpl"`. + + 2. Added the Xalan jar into my maven pom. + +My guess is that the default xml parsing mechanism supplied within the +JDK (I am using 1.6.0_03) does not work right in this context and does +not throw up any error either. When I switched to Xalan this way it +works. This is not a Camel issue, but might need a mention on the xslt +component page. + +Another note, jdk 1.6.0_03 ships with JAXB 2.0 while Camel needs 2.1. +One workaround is to add the 2.1 jar to the `jre/lib/endorsed` directory +for the jvm or as specified by the container. + +Hope this post saves newbie Camel riders some time. +________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ + +[[XSLT-SeeAlso]] +See Also +^^^^^^^^ + +* link:configuring-camel.html[Configuring Camel] +* link:component.html[Component] +* link:endpoint.html[Endpoint] +* link:getting-started.html[Getting Started] + http://git-wip-us.apache.org/repos/asf/camel/blob/fd256485/docs/user-manual/en/SUMMARY.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md index b06a254..0f3e099 100644 --- a/docs/user-manual/en/SUMMARY.md +++ b/docs/user-manual/en/SUMMARY.md @@ -97,6 +97,7 @@ * [Timer](timer.adoc) * [Validator](validator.adoc) * [VM](vm.adoc) + * [Xslt](xslt.adoc) * Components * [Async Http Client (AHC)](ahc.adoc)
