I have the following in an XLST document
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:str="http://xsltsl.org/string" xmlns:dt="http://xsltsl.org/date-time" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes">
<xsl:if test="document('../folder/somefile.xml')">
<!-- do stuff -->
</xsl:if>
In IE8 and IE9 attempting to process this file results in a JavaScript error,"The system cannot locate the object specified" - and the transform bugs out.
I have read about a 'doc-available' function in XLST2.0, but attempting to use it just gives me an error that the function is not available.
I have seen this question: How check document is available in xsl? - but I'd prefer not to add processor dependent code, so I'm hoping I'm just missing something with 'doc-available'.
I think the XSLT 1.0 specification (and MSXML used by IE is an XSLT 1.0 processor) allows the XSLT processor do either "signal an error" or to continue by returning an empty node set if a document() call fails. Thus MSXML reporting an error is allowed and not a bug. You will need to make sure outside of XSLT that the file exists.
Related
This transform called docUri.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" expand-text="yes">
<xsl:output method="text"/>
<xsl:template match="document-node()">{document-uri(.)}</xsl:template>
</xsl:stylesheet>
does not return the name of the xml file being processed when called from exist-db with this xQuery
xquery version "3.1";
transform:transform(doc("/db/apps/data/aDatabaseFile.xml"),
doc("/db/apps/docUri.xsl"),())
It should return "/db/apps/data/aDatabaseFile.xml"
Looks like there was a similar issue on MarkLogic XSLT doc(uri) or document(uri) function not resolving uri in context of content database?
When transform:transform is executed in eXist-db, the datafile is handed off to Saxon for transformation. At that point Saxon is unaware of the node context of the file. It therefore cannot report the "name" of the file.
If one wants the name (or any other data related to its node), then Saxon has to be told how to retrieve the document from the database. To do this one passes the full path to the document as a parameter to the transform:transform function's third argument ($parameters). This parameter is made available to Saxon inside the XSL stylesheet (matching on name) and it will return what you need
Parameter as third argument:
let $parameters :=
<parameters>
<param name="my_saxon_path" value="xmldb:exist://db/apps/data/aDatabaseFile.xml"/>
</parameters>
In your XSL stylesheet you reference the parameter as
<xsl:param name="my_saxon_path"/>
and then use the parameter as a regular node:
<xsl:template match="document-node()">{document-uri($my_saxon_path)}</xsl:template>
This is explained fully in the eXist-db documentation.
The side-effect of this is that you don't pass the document directly into transform:transform function if Saxon can access it directly through the supplied path. Balance these techniques is dependant on where your code is optimised and where you want the heavy lifting to be done: by eXist's engine, or Saxon's....
I am planning to used XSL version 3.0 for my WSO2 EI application. Because, I need to map JSON to JSON and JSON to XML in my application. Currently I have try with version 2.0. Please refer following code for current implementation.
I need to know how change this version and which jar required in WSO2EI for xsl version 3.0.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:param name="STATIC_BODY_PARAM"></xsl:param>
<xsl:template match="/availabilityRequest">
<availabilityRequest>
<control>
<userName>
<xsl:value-of select="control/userName" />
</userName>
<passWord>
<xsl:value-of select="control/passWord" />
</passWord>
</control>
....................
</availabilityRequest>
</xsl:template>
</xsl:stylesheet>
When I used version as 3.0, I got following error message. I have added your further reference.
ERROR - XSLTMediator Error creating XSLT transformer using : Value {name ='null', expression =fn:concat('gov:repository/transformation/',$ctx:uri.var.travel_type,'_',$ctx:uri.var.activity,'_',$ctx:uri.var.supplier_id,'_in.xslt')}
net.sf.saxon.trans.LicenseException: Requested feature (XSLT 3.0) requires Saxon-PE
at net.sf.saxon.Configuration.checkLicensedFeature(Configuration.java:584)
at net.sf.saxon.PreparedStylesheet.setStylesheetDocument(PreparedStylesheet.java:331)
at net.sf.saxon.PreparedStylesheet.prepare(PreparedStylesheet.java:207)
at net.sf.saxon.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:132)
at org.apache.synapse.mediators.transform.XSLTMediator.createTemplate(XSLTMediator.java:467)
I don't know anything specifically about WSO2EI, but it appears (from your link) that it is currently running with some older version of Saxon-HE.
Simply substituting the Saxon 9.9 JAR file for the one that is distributed with the product may work, or it may not. It's very likely to work, but it's possible that the stylesheets, or the calling application, depend on something in Saxon that has changed.
If you've tried something, there's no point telling us it doesn't work. You need to tell us exactly how it failed.
You should try running a stylesheet that outputs the value of system-property('xsl:product-version') so you have positive confirmation of which Saxon version is being picked up.
You don't need to make any changes to your stylesheets to use XSLT 3.0 features, but it's a good idea to change the version attribute to version="3.0" for documentation reasons.
I have fixed above problem using following information.
I got the 30 trail license key with registering http://www.saxonica.com/download/download.xml (saxon-license.lic) and it put into /wso2ei-6.4.0/ folder
Remove this jar (saxon.he_9.4.0.wso2v1.jar) on following location. (/wso2ei-6.4.0/wso2/components/plugins)
Also put this jar (saxon9ee.jar) http://www.saxonica.com/download/SaxonEE9-4-0-6J.zip into /wso2ei-6.4.0/lib location
Restart the wso2ei-6.4.0 server
Now xsl:stylesheet version="3.0" working without any issue.
I have got those details from following link. Many thanks for that.
http://nandikajayawardana.blogspot.com/2012/12/how-to-replace-saxonhe940wso2v1jar-in.html
Is there a way to make eXist to return processing instruction as it is? It seems it somehow ignores it in the output.
Processing instructions are very useful if I use XEP as my rendering engine, hence it would be great to be able to preserve them before the root of the XSL-FO document or immediately after its start.
If I have in the template:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:tei="http://www.tei-c.org/ns/1.0" version="2.0">
<xsl:template match="/">
<fo:root>
<?xep-pdf-page-layout two-columns-right?>
It simply returns:
<fo:root xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
I’ve tried to touch preserving of processing instructions with:
declare option exist:serialize "method=xhtml media-type=text/xml process-xsl-pi=yes"; in the prolog of my query but to no avail.
UPDATE I
The steps of my scenario are:
loading the document from the DB
passing it to the transform:transform() function
whilst calling the transform:transform() function, I pass to it one basic stylesheet, which includes other stylesheets
I need to add the processing instruction to a stylesheet for pages-masters, which covers the root of the FO document later used by the rendering engine. This stylesheet is included (<xsl:include/>) into the basic one (gathering all the stylesheets) and passed to the function.
With XSLT, to output a processing instruction use https://www.w3.org/TR/xslt/#creating-processing-instructions, that is <xsl:processing-instruction name="xep-pdf-page-layout">two-columns-right</xsl:processing-instruction> to have the pi <?xep-pdf-page-layout two-columns-right?> in the transformation result.
Some of my stylesheets are a bit large and some of their parts are repeating. I would like to use XInclude for them—which would allow me to separate them aside the whole stylesheet. I can’t use xsl:import or xsl:include here because I need to inject them into the specific place for generating bookmarks and active links (for XSL-FO).
If I use:
<xi:include href="/db/apps/tested-bunny/resources/xsl-fo/common/bookmark-tree.xml/>
… the .fo file produced really includes the part. However, the part is untranslated, which means it is there as is in the source. The XSL-FO processor thus ignores it and the pdf result is without bookmarks.
As for the separated part—I saved it as a regular XML file with two namespaces declared in the root element:
<fo:bookmark-tree xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:if test="$head-level ge '1'">
...
If I try to include the same code snippet in a form of XSL stylesheet, it is the same—it is injected there properly but it does not add its functionality to the whole stylesheet, it is there still untranslated.
Is there any specific practice or limitation I am not aware of? How to do that properly?
For me, the working solution was not XInclude but xsl:include and calling the template at the proper time:
...
</fo:declarations>
<!-- Bookmarks from the external stylesheet -->
<xsl:call-template name="bookmark-tree"/>
<fo:page-sequence master-reference="title-page">
...
I created the proper stylesheet. The important thing was to set the root element to the current context:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="2.0">
<xsl:template name="bookmark-tree" match=".">
<fo:bookmark-tree>
...
And of course, it was necessary to include the stylesheet into the one where I call the template:
<xsl:include href="common/bookmark-tree.xsl"/>
For now, I consider this question as answered.
I hope this is a dumb user error - but - I have an XSLT file that should be using XSL 2.0 - however, whenever I try to use XSL 2.0 functions, like replace() for example, I get an error saying the function is not recognized
System.Xml.Xsl.XsltException: 'replace()' is an unknown XSLT function.
I interpret this error to mean that the file is not getting properly defined or processed as XSL 2.0 but not sure what I'm doing wrong.
Here is how I construct the version:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml">
Just to ensure there is an answer: you are using an XSLT processor (System.Xml.Xsl) that lacks support for XSLT 2.0.