saxon transform vs saxon.jar document() behave differently - xslt

I have a stylesheet with a document() function. It finds the external document when i run it with saxon's transform on .Net, but not when i run it using java -jar saxon...
Please tell me that is well documented behavior and where it is documented!
Thank you guys!
EDIT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<root>
<xsl:variable name="dict" select="document('file:../data/mpxvoc.xml')"/>
<xsl:message>
<xsl:value-of select="doc-available('file:../data/mpxvoc.xml')"/>
<xsl:value-of select="$dict/*/*[1]"/>
</xsl:message>
</root>
</xsl:template>
</xsl:stylesheet>
EDIT2: Yes, same version!
EDIT3: Beginning of -t output on .NET/transform
C:\Users\mauri\OneDrive\smbdata\EM\SM-Plains\20200806>transform -t -s:2-MPX\vfix.mpx -xsl:C:\Users\mauri\eclipse-workspace\Pipeline\xsl\dtest.xsl -o:o.xml
Saxon-HE 9.9.1.6N from Saxonica
.NET 4.0.30319.42000 on Microsoft Windows NT 6.2.9200.0
URIResolver.resolve href="file:/C:/Users/mauri/eclipse-workspace/Pipeline/xsl/dtest.xsl" base="null"
Stylesheet compilation time: 1.25987s (1259.87ms)
Processing file:/C:/Users/mauri/OneDrive/smbdata/EM/SM-Plains/20200806/2-MPX/vfix.mpx
Using parser org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:///C:/Users/mauri/OneDrive/smbdata/EM/SM-Plains/20200806/2-MPX/vfix.mpx using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 222.8786ms
Tree size: 42580 nodes, 902487 characters, 26182 attributes
Building tree for file:///C:/Users/mauri/eclipse-workspace/Pipeline/data/mpxvoc.xml using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 59.3813ms
Tree size: 20788 nodes, 725994 characters, 10214 attributes
...
Java version:
C:\Users\mauri\OneDrive\smbdata\EM\SM-Plains\20200806>java -jar "C:\Program Files\Saxonica\SaxonHE10-2J\saxon-he-10.2.jar" -t -s:2-MPX\vfix.mpx -xsl:C:\Users\mauri\eclipse-workspace\Pipeline\xsl\dtest.xsl -o:o.xml
Saxon-HE 10.2J from Saxonica
Java version 1.8.0_261
Stylesheet compilation time: 635.9066ms
Processing file:/C:/Users/mauri/OneDrive/smbdata/EM/SM-Plains/20200806/2-MPX/vfix.mpx
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:/C:/Users/mauri/OneDrive/smbdata/EM/SM-Plains/20200806/2-MPX/vfix.mpx using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 348.0487ms
Tree size: 42580 nodes, 902487 characters, 26182 attributes
URIResolver.resolve href="file:../data/mpxvoc.xml" base="file:/C:/Users/mauri/eclipse-workspace/Pipeline/xsl/dtest.xsl"
falseError FODC0002 while evaluating xsl:message at line 12 of file:/C:/Users/mauri/eclipse-workspace/Pipeline/xsl/dtest.xsl: Document has been marked not available: file:../data/mpxvoc.xml
Execution time: 414.5074ms
Memory used: 62Mb
URIResolver shows different bases. Is that it and is there a quick fix to get the same result in java?

The URI file:../data/mpxvoc.xml is not a valid URI acccording to RFC 8089. Saxon however takes a liberal approach to URIs, in this context it passes the URI to the XML parser "as is", and if the parser is prepared to accept it then that's fine. At this point differences between platforms may well appear.
The solution is to avoid using URIs that don't conform to the standards. If you want a relative URI resolved against the base URI of the stylesheet, then drop the "file:" part.
RFC 8089 was only published in 2017, and until then the specs for the file URI scheme were hopelessly vague. The 2017 spec was far too late to make a real difference, since by then existing platforms like Java and .NET had to maintain compatibility with their respective past decisions. But if you stick to RFC 8089, you should be able to achieve reasonable portability.

Related

wso2ei-6.4.0 and XSLT 3.0 support

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

XSLT Getting two different output for same input XML for same XSL

I have been trying my XSLT code in the online tool [XSLT 1.0 processor]:
http://www.freeformatter.com/xsl-transformer.html
Recently, I had to make use of xs:dateTime and hence started using the tool that uses XSLT 2.0 processor,
http://xsltransform.net/
Now, when i was trying to solve a problem, i see that i get different output for the same input XML in these two processors. The code posted here is not the real code i am working on; this is to simulate the weird output i faced.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<book>
<title></title>
</book>
<phone>apple</phone>
</items>
XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:template match="/">
<items><xsl:apply-templates select="items/*" /></items>
</xsl:template>
<!-- ignore empty elements -->
<xsl:template match="*[not(normalize-space())]" />
<xsl:template match="book">
<newbook><xsl:apply-templates /></newbook>
</xsl:template>
<xsl:template match="title">
<newtitle><xsl:apply-templates /></newtitle>
</xsl:template>
<xsl:template match="phone">
<newphone><xsl:apply-templates /></newphone>
</xsl:template>
</xsl:stylesheet>
Output from http://xsltransform.net/ : [output 1]
<?xml version="1.0" encoding="UTF-8"?>
<items>
<newbook>
<newtitle/>
</newbook>
<newphone>apple</newphone>
</items>
Output from http://www.freeformatter.com/xsl-transformer.html : [output 2]
<?xml version="1.0" encoding="UTF-8"?>
<items>
<newphone>apple</newphone>
</items>
Expected output XML is output 2 .
Any idea why this different output behavior?
note: I looked at another SO question: Generating two different outputs for the same XSL file?, but that is different.
Edit
To add more clarity on which tool produced which output:
http://xsltransform.net/ produced output 1
http://www.freeformatter.com/xsl-transformer.html produced output 2
Update[02/10/2014] - regarding solution
Since the correct answer was first provided by Jim Garrison, that's marked as answer. However, there are other important points as well, as pointed out by others, Hence I am wrapping up all here.
<xsl:template match="*[not(normalize-space())]" />
The above template eliminates the empty nodes in both XSLT1 and XSLT2. Hence output 2 is correct
*Reason for getting output 1 from the tool - http://xsltransform.net/ :*
As #michael.hor257k pointed out, there are two templates that matches the <book> element.
The tool was using Saxon-HE 9.5.1.3, and the output 1 behavior was probably a bug that was fixed in the latest maintenance release [#Michael Kay explained well in his answer]
As #Ian Roberts mentioned in his answer, there is a concept of default priorities that are assigned to different types of templates.
Changing the template syntax to:
<xsl:template match="*[not(normalize-space())]" priority="2"/>
yields the same output in both the tools regardless of Saxon version, because we are explicitly defining the priority to the template.
Output 2 is correct. I ran your example in Oxygen/XML, using both XSLT1 and XSLT2 and got the correct results for both. Your template
<xsl:template match="*[not(normalize-space())]" />
eliminates the empty nodes in both XSLT1 and XSLT2.
Therefore the only possible conclusion is that the online tool that produced your Output 1 has a bug.
I get the correct result running with Saxon-EE 9.5.1.4; the xsltransform site is running Saxon-HE 9.5.1.3. It's probably a bug that we fixed in the latest maintenance release; I'll do some chasing to see if I can finger it.
Note that an empty <book> element matches two of your templates:
<xsl:template match="*[not(normalize-space())]" />
and:
<xsl:template match="book">
<newbook><xsl:apply-templates /></newbook>
</xsl:template>
The same thing applies to an empty <title> element. Such conflicts must be resolved by the XSLT processor, using the priorities specified in the XSLT specification.
The result you report from http://xsltransform.net/ is generated by Saxon 9.5.1 - an XSLT 2.0 engine. You will get a different result (on the same site) if you switch to an XSLT 1.0 engine (Saxon 6.5 or Xalan 2.7.1).
I don't know if the conflict resolution rules have changed in XSLT 2.0 compared to XSLT 1.0; I am getting a different result myself when using Saxon 8.9 - also an XSLT 2.0 processor. Perhaps we will be fortunate enough to hear from Michael Kay regarding this difference (I have added a Saxon tag to your question to get his attention)..
Output 2 is definitely the correct one according to both the 1.0 and 2.0 XSLT specs for the stylesheet you give in the question. However you say this is simplified when compared to your real stylesheet.
The thing that makes it work is the default priorities that are assigned to different types of templates. These are the same in both XSLT versions, and a match pattern that involves a predicate will overrule one that is just a single element name test.
However a match that involves hierarchy (e.g. match="items/book") or anything more complex than just a single element name will get the same priority as the *[....] rule by default - 0.5. If you've got any of these kinds of patterns in your real XSLT then you need to add an explicit priority higher than 0.5 to the "blank-suppressor" template.
<xsl:template match="*[not(normalize-space())]" priority="2"/>

How to create wsproxy with xslt transformation in jboss-esb

JBoss ESB 4.11
Hello!
I work with the JBoss ESB 4.11, we are create webservice proxy and we need transform the payload message with xslt transformation. But I can find any functional example to use.
This is a example of the original message
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cim:ESRGERAL xmlns:cim="http://iec.ch/TC57/2007/profile#">
<cim:Terminal>
<cim:mRID>_012345_term</cim:mRID>
<cim:aliasName>term01</cim:aliasName>
<cim:name>term01</cim:name>
and this is the xslt file
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="*">
<ESRGERAL xmlns:cim="http://iec.ch/TC57/2007/profile#">
<xsl:for-each select="//cim:Terminal">
<Terminal>
<mRID>
<xsl:value-of select="cim:mRID"/>
</mRID>
<name>
<xsl:value-of select="cim:aliasName"/>
</name>
</Terminal>
</xsl:for-each>
</cim:ESRGERAL>
</xsl:template>
</xsl:stylesheet>
I need to help to create the correct configuration in jboss-esb.xml, this two files work fine when I use a java implementation, but I can make the same in jboss esb.
If you want to use XSLT for transforming XML-payloads then I believe the XsltAction is what you are looking for:
http://docs.jboss.org/jbossesb/docs/4.11/manuals/html/Programmers_Guide/index.html#OOB-transformers-xsltaction
Not sure that this fully answers your question but in any case, your use case seems very straight forward so I believe JBoss ESB will support it right out of the box without the need for custom code.
One caveat is if you really need to use XSLT 2.0 and not XSLT 1.0 (like in your example), then you will need to do something to make it load your 2.0 XSLT library instead of the standard.

Cannot find external method "..." (must be public) XSLT

I'm trying to do some operation on dates using XSL. I found a tutorial on IBM developerWorks with this script.
<?xml version="1.0" encoding="utf-8"?>
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times"
version="1.0"
>
<xsl:output method="html"/>
<!-- B -->
<xsl:variable name="now" select="date:date-time()"/>
<xsl:template match="/">
<!-- The rest of the Web site HTML material would go here -->
<xsl:call-template name="date-section"/>
</xsl:template>
<xsl:template name="date-section">
<p>This page was loaded at <xsl:text/>
<!-- C -->
<xsl:value-of select="concat(date:hour-in-day($now), ':',
date:minute-in-hour($now), ':',
date:second-in-minute($now))"/>
<xsl:text> on </xsl:text>
<xsl:value-of select="concat(date:day-in-month($now), ' ',
date:month-name($now), ' ',
date:year($now))"/>
</p>
<p>
<!-- D -->
<xsl:variable name="days-elapsed"
select="concat('-P',date:day-in-month($now),'D')"/>
<xsl:variable name="one-month-hence"
select="date:add($now, 'P1M')"/>
<xsl:variable name="next-month-start"
select="date:add($one-month-hence, $days-elapsed)"/>
<xsl:variable name="seconds"
select="date:seconds(
date:difference($now, $next-month-start)
)"/>
<xsl:text>The next month starts in </xsl:text>
<xsl:value-of select="$seconds div (3600*24)"/>
<xsl:text> days</xsl:text>
</p>
</xsl:template>
I get the following errors:
[ERROR]: Cannot find external method 'com.sun.org.apache.xalan.internal.lib.ExsltDatetime.add' (must be public).
[ERROR]: Cannot find external method 'com.sun.org.apache.xalan.internal.lib.ExsltDatetime.difference' (must be public).
[ERROR]: Cannot find external method 'com.sun.org.apache.xalan.internal.lib.ExsltDatetime.seconds' (must be public).
[ERROR]: Cannot convert data-type 'void' to 'real'.
[FATAL]: Could not compile stylesheet
Any ideas how to fix it. I'm using IntelliJ to run the xsl.
Ultimately I want to to be able to add days to a date. For some reason when I try to use xsl 2 date functions it just tells me they do not exist(And yes I do change the header to version 2 :) ). So I'm trying to make it work with a 3rd party library. The date-time() function from the http://exslt.org/dates-and-times namespace is working but I can't seam to be able to call other functions form that namespace.
the question is a bit old but the answers were, IMHO, not quite correct and my answer might help some other people stumbling upon this thread (as I just did):
The functions used are XSLT 1.0 extension functions, there are different modules (e.g. dates-and-times), each with mandatory and optional functions (and elements). See EXSLT
The issue here is that XALAN does support the module dates-and-times, but not all optional functions.
As suggested, you can surely try to find a "better" XSLT-Processor, but it might require some work to integrate. I personally use on the Linux command line xsltproc, which supports more of the dates-and-times module (try xsltproc --dumpextensions | sort for an overview).
Alternatively, you could try the approach describing how to get current date and time in XSLT 1.0. I haven't tried it myself yet (as said, xsltproc is a good enough workaround), but using a similar approach you should be able to implement what you need without having to touch your tool/java code.
For sake of completeness, my tool with the same problem is Freeplane from freeplane.org, which also uses XALAN (I guess that it's part of standard Java libraries) and fails on similar dates-and-times functions.
Hope this helps,
Eric
I don't know Xalan, so I don't know why it's failing to find these methods.
But if you want to use the XSLT 2.0 date/time functions, you need to invoke an XSLT 2.0 processor, and the obvious one for the Java environment is Saxon (current version is 9.4). Switching processor requires a little bit more than changing the version number: for example, if you are running it from the command line then you will need to use a different command.

xsl document test failing in IE8 and 9?

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.