XSLT 2.0 functions don't work in Safari and Chrome? - xslt

This is my XML document:
<?xml version="1.0"?>
<?xml-stylesheet type='text/xml' href='/foo.xsl'?>
<document/>
This is /foo.xsl:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:foo="foo"
version="2.0" exclude-result-prefixes="xs">
<xsl:function name="foo:const" as="xs:string">
<xsl:text>ABC</xsl:text>
</xsl:function>
<xsl:template match="/">
<xsl:value-of select="foo:const()"/>
</xsl:template>
</xsl:stylesheet>
Works fine with Saxon 8.7 and produces ABC, as an output. But in Safari and in Chrome this document doesn't work (just an empty page with no error messages). What is it about? Safari and Chrome don't support XSL functions?

Sadly, none of the browsers yet support XSLT 2.0 natively. I think they're all waiting for the others to move first.

Have you tried using SaxonCE?
This is Saxon 9.x implemented in Javascript -- it is reported to work with any of the five major browsers.
At the last Balisage conference Michael Kay (#Michael Kay ) demoed this working on his iPhone.

Related

how to compress and decompress xml present in URL C++

I writing the saml SP in C++ but don't know how to compress the xml.
http://acme.com:16006/idp/samlv20?SAMLRequest={xmlCompressedandBase64encodedString}
Now xmlCompressedandBase64encodedString is the problematic part I know Base64 encoding but xml compression I am not aware off.
My saml request will be looking like this :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<samlp:AuthnRequest
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
xmlns:enc="http://www.w3.org/2001/04/xmlenc#"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
ID="id-_Abcd1234&-rQjG"
Version="2.0"
IssueInstant="2018-05-03T06:02:22Z"
Destination="http://acme.com:16006/idp/samlv20">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
https://flight.com::14213/sp
</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true"/>
</samlp:AuthnRequest>
Same goes for decompression of SamlRespone.
There is a wikipedia article indicating that you should use DEFLATE altorithm.
zlib is one of the most famous library that implements DEFLATE algorihm. I heard Boost.iostream can also do that using zlib as dependency, but I am not sure.

How to traverse through result set saved in a variable in xslt

<xsl:variable name="result">
<values>
<value>1</value>
<value>1</value>
<value>1</value>
<value>1</value>
</values>
<xsl:variable>
<xsl:for-each select="$result/values/value">
<xsl:copy-of select=".">
</xsl:for-each>
When i try to traverse with result set in for each loop its throwing error in eclipse javax parser but its working fine online xslt tools. How to make it work in eclipse also.
I suppose that Eclipse uses Xalan (XSLT 1.0) and during online testing you used another XSLT engine and maybe XSLT 2.0.
Make the following changes:
In the stylesheet tag add xmlns:exsl="http://exslt.org/common"
and extension-element-prefixes="exsl" (it will be used below).
Change your for-each instruction to
<xsl:for-each select="exsl:node-set($result)/values/value">.
I tested these changes on xslttransform with Xalan engine and it works
(on Saxon 9... engine it doesn't work, as "newer" Saxon versions do not
support exsl).
You have also to tidy up your source XML:
Change <xsl:variable> to </xsl:variable> (it is a closing tag).
Change <xsl:copy-of select="."> to <xsl:copy-of select="."/>
(add missing "/" at the end).
To build up your knowledge, read about node-set function.
Sometimes it is needed in XSLT 1.0.
If you are using Eclipse then there is nothing stopping you moving forward to XSLT 2.0. Install Saxon, and the problem will go away. XSLT 1.0 is 17 years old and was superseded over 10 years ago. There are some environments where you still have no choice, but in the Java world, it's time you moved forward.

Java XSLT processing throws TransformerConfigurationException when run on another machine

I am running a Java application which is supposed to do some XSLT processing based on javax.xml.transform.Transformer. I developed it on an older notebook using java-7-openjdk-amd64.
When I run it on another machine with java-8-openjdk-amd64 installed the Transformer throws the following exception:
javax.xml.transform.TransformerConfigurationException: Failed to
compile stylesheet. 1 error detected.
XPST0017: XPath syntax error [...]
Cannot find a matching 1-argument function named {http://xml.apache.org/xslt/java}java.text.SimpleDateFormat.new()
at net.sf.saxon.PreparedStylesheet.prepare(PreparedStylesheet.java:176)
at net.sf.saxon.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:139)
at net.sf.saxon.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:91)
The xsl file looks like this (leaving out unimportant details):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java" exclude-result-prefixes="java">
<xsl:template match="/">
<html>
<body>
<h1>Test Report</h1>
<h2>Test run</a> at
[<xsl:value-of
select="java:format(java:java.text.SimpleDateFormat.new('dd.MM.yyyy HH:mm:ss'), java:java.util.Date.new())" />]
</h2>
So the Transformer obviously has a problem with invoking SimpleDateFormat, but why? I could not find any information about this in respect to Java7 vs. Java8. I even copied the Jar file compiled with Jdk7 an and ran it on the other machine. Same problem, so it seems to be a runtime issue.
There are some Q+A on SO about java and XSLT but nothing turned out to be useful for me.
It turned out be that this declaration <xsl:stylesheet version="2.0" does not ensure that XSLT v2.0 is actually used. javax.xml.transform.Transformer "secretly" used XSLT v1.0 on the old machine (with java-7-openjdk-amd64) and XSLT v2.0 with Saxon v9.1.0 on the other machine (with java-8-openjdk-amd64).
The dependency was set by a maven pom.xml at compile time. But apparently this had no effect when running it with Jre7. I could have noticed it by looking at the stack trace (net.sf.saxon.TransformerFactoryImpl) but since there were no errors before, I was not aware of any specific TransformerFactory implementation.

Multiple XSLT files in a single pipeline with ant

I have multiple XSLT files that I'm using to process my source XML in a pipeline. I know about the trick with exsl:node-set but after having some issues with this workflow, I took the decision to split the various passes into separate XSL files. I'm much happier with the structure of the files now and the workflow works fine in Eclipse. Our release system works with ant. I can process the files like this:
<xslt basedir="src-xml" style="src-xml/preprocess_1.xsl" in="src-xml/original.xml" out="src-xml/temp_1.xml" />
<xslt basedir="src-xml" style="src-xml/preprocess_2.xsl" in="src-xml/temp_1.xml" out="src-xml/temp_2.xml" />
<xslt basedir="src-xml" style="src-xml/preprocess_3.xsl" in="src-xml/temp_2.xml" out="src-xml/temp_3.xml" />
<xslt basedir="src-xml" style="src-xml/finaloutput.xsl" in="src-xml/temp_3.xml" out="${finaloutput}" />
But this method, going via multiple files on disk, seems inefficient. Is there a better way of doing this with ant?
Update following Dimitre's suggestion
I've created myself a wrapper around the various other XSLs, as follows:
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:fn='http://www.w3.org/2005/xpath-functions' xmlns:exslt="http://exslt.org/common">
<xsl:import href="preprocess_1.xsl"/>
<xsl:import href="preprocess_2.xsl"/>
<xsl:import href="preprocess_3.xsl"/>
<xsl:import href="finaloutput.xsl"/>
<xsl:output method="text" />
<xsl:template match="/">
<xsl:apply-imports />
</xsl:template>
</xsl:stylesheet>
This has... not worked well. It looks like the document had not been preprocessed before the final output XSL ran. I should perhaps have been clearer here: the preprocess XSL files are modifying the document, adding attributes and the like. preprocess_3 is based on the output of ..._2 is based on ..._1. Is this import solution still appropriate? If so, what am I missing?
The more efficient method is to perform a single, multipass transformation.
The files can remain as they are -- they will be imported using xsl:import instructions.
The savings are obvious:
Just one initiation (loading of the XSLT processor).
Just one termination.
Eliminates the two intermediate files and their creation, writing into, closing and deleting.
Hmm, you say I know about the trick with exsl:node-set, but you don't use it in your attempt ("Update following Dimitre's suggestion"). In case you don't know it, or for the others (like me) who don't know how to perform multipass transformation, here is a nice article: Multipass processing.
The drawback of this approach is that it requires engine specific xsl code. So if you know the engine, you could try this. If you don't know the engine, you could try with solutions from result tree fragment to node-set: generic approach for all xsl engines.
Looking at these sources one conclusion is sure: your current solution is more readable. But you are seeking efficiency, so some readability may be sacrificed.

Xalan date extension problem

i'm trying to use the ubuntu cli version of xalan:
Xalan version 1.10.0
Xerces version 2.8.0
My problem is how to kick in with date functions. I tryed like this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date">
<xsl:import href="date/date.xsl" />
<xsl:output method="text" indent="yes" />
date: <xsl:value-of select="date:date()" />
</xsl:stylesheet>
It gives me back this message:
XSLException Type is: XalanXPathException
Message is: The function number 'http://exslt.org/dates-and-times:date' is not available. (file:///home/user/test.xsl, line x, column y)
What files or what do i need to change to make those date functions work?
You need to use a later version of Xalan.
From the Xalan J.2.7.1 documentation:
EXSLT extensions
Xalan-Java supports the EXSLT
initiative to provide a set of
standard extension functions and
elements to XSLT users. Xalan-Java
includes implementations for the
following EXSLT extension modules:
EXSLT common functions EXSLT math
functions EXSLT set functions
EXSLT date-and-time functions
EXSLT dynamic functions
EXSLT string functions
The EXSLT func:function and
func:result elements (see EXSLT -
func:function)
The documentation shows that it has built-in beta implementations for that subset, however it does not say you cannot import and use the functions from exslt.org. Why can't you? Does Xalan-c++ not support importing functions?
Note that, I was able to get the templates working. Just not the functions.
From http://xml.apache.org/xalan-c/extensionslib.html
Xalan-C++ includes beta
implementations for functions in four
of the EXSLT namespaces (some are
calls to extension already in the
Xalan namespace).
And from http://xml.apache.org/xalan-c/apiDocs/XalanEXSLTDateTimeImpl_8hpp.html, it looks like only date:date-time() have been implemented.