Bug 21525 - [PATCH] XSLT/param@expression used as string instead of as expression as documented
Summary: [PATCH] XSLT/param@expression used as string instead of as expression as docu...
Status: RESOLVED FIXED
Alias: None
Product: Ant
Classification: Unclassified
Component: Core tasks (show other bugs)
Version: 1.5.3
Hardware: All All
: P3 normal (vote)
Target Milestone: 1.9.3
Assignee: Ant Notifications List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-07-11 19:09 UTC by Daniel B.
Modified: 2013-12-05 18:51 UTC (History)
1 user (show)



Attachments
patch that adds support of several data types and XPath expressions in XSLT parameters (12.17 KB, patch)
2013-06-28 17:33 UTC, František Kučera <xkucf03/>
Details | Diff
example of usage (20.00 KB, application/gzip)
2013-06-28 17:36 UTC, František Kučera <xkucf03/>
Details
improved patch - adds XSLTLiaison4 interface for compatibility (15.10 KB, patch)
2013-10-15 16:12 UTC, František Kučera <xkucf03/>
Details | Diff
improved patch - ParamType implemented as a true enum (14.83 KB, patch)
2013-10-15 18:49 UTC, František Kučera <xkucf03/>
Details | Diff
improved patch - adds documentation and tests (21.85 KB, patch)
2013-10-18 18:56 UTC, František Kučera <xkucf03/>
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel B. 2003-07-11 19:09:48 UTC
For the XSLT task, in a nested param element, it seems that the value of 
the expression attribute is passed as a string value instead of being
passed as an expression, as the documentation specifies.

The documentation (.../docs/manual/CoreTasks/style.html) says:

    XSL expression to be placed into the param.  To pass a text value into 
    the style sheet it needs to be escaped using single quotes.

Although the wording "XSL expression to be placed into the param" is 
ambiguous (or wrong?), the second sentence clearly implies that the value of 
the Ant attribute is to be evaluated as an XSLT expression and the resulting 
value is to be assigned to the XSLT parameter.

However, the XSLT parameter is _not_ assigned the result of evaluating
the Ant attribute value as an XSLT expression.  Instead, it is assigned a 
string value equal to the Ant attribute value.

In the test case below, notice in the output how the parameter's value acts 
as the string value resulting from the string literal:

    '1 = 0'

instead of as the boolean value resulting from the expression:

    1 - 0

Therefore, the Ant attribute value is not being evaluated as an expression.


If the Ant attribute value is supposed to be evaluated as an expression, then:

1.  There is a bug in the code.

2.  The first sentence of the attribute documentation is a bit wrong and
    confusing.  (The expression is not placed into the parameter.)

    It should say something like:

        XSL expression whose value to assign to the parameter.

    or

        XML expression to evaluate and whose value to assign to the parameter.


If the Ant attribute value was never supposed to be evaluated as an expression,
then:

1.  The second sentence of the documentation is wrong or is misleading and 
    must be fixed.

2.  The first sentence should say something like:

        string value to assign to the parameter


================================================================================
Test case:

build.xml:

<project default="default" >

  <target name="default" >

    <xslt in="input.xml" style="transform.xsl" out="output.xml" >
      <param name="param" expression="1 = 0" />
    </xslt>

  </target>

</project>

input.xml:

<doc>
</doc>

transform.xml:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >

  <xsl:param name="param" />

  <xsl:template match="/" >
    $param            : <xsl:value-of select="$param" />;
    $param  = '1 = 0' : <xsl:value-of select="$param = '1 = 0'" />;
    $param  = (1 = 0) : <xsl:value-of select="$param = (1 = 0)" />;

    1 = 0             : <xsl:value-of select="1 = 0" />;
    1 = 0   = 1 = 0   : <xsl:value-of select="1 = 0 = 1 = 0" />;
    1 = 0   = (1 = 0) : <xsl:value-of select="1 = 0 = (1 = 0)" />;

    '1 = 0'           : <xsl:value-of select="'1 = 0'" />;
    '1 = 0' = '1 = 0' : <xsl:value-of select="'1 = 0' = '1 = 0'" />;
    '1 = 0' = (1 = 0) : <xsl:value-of select="'1 = 0' = (1 = 0)" />;
    <xsl:apply-templates />
  </xsl:template>

</xsl:transform>


Resulting output.xml:

<?xml version="1.0" encoding="UTF-8"?>

    $param            : 1 = 0;
    $param  = '1 = 0' : true;
    $param  = (1 = 0) : false;

    1 = 0             : false;
    1 = 0   = 1 = 0   : true;
    1 = 0   = (1 = 0) : true;

    '1 = 0'           : 1 = 0;
    '1 = 0' = '1 = 0' : true;
    '1 = 0' = (1 = 0) : false;
Comment 1 Antoine Levy-Lambert 2003-07-26 16:44:39 UTC
I have tried your testcase and I could reproduce it.
So I have changed the documentation of the style task and the JavaDoc of the 
XSLTProcess class.
I am closing the bug for now, but if an XML guru wants to throw a look at the 
issue, fine.
Cheers,
Antoine
Comment 2 Daniel B. 2003-07-26 18:13:27 UTC
> I have tried your testcase and I could reproduce it.

Did it work the same way on several different XSLT processors?

Also, do you know if the the XSLT processors take just string 
values, or also take expressions?
Comment 3 Antoine Levy-Lambert 2003-07-26 20:35:12 UTC
The calls to the XSLTProcessor go through TRAXLiaison.
This goes to jaxp.
I do not know how the 2 other old liaisons behave.
Comment 4 František Kučera <xkucf03/> 2013-06-28 17:32:13 UTC
After almost ten years it is time to reopen this bug.

Parameters in XSLT can be of many data types, they can be booleans, numbers, nodes etc. not only strings.

Current version of Ant supports only strings. And it is problem if you need e.g. boolean to be evaluated in XSLT IF/WHEN.
In such case you have to do a workaround in XSTL template like manual casting from string to boolean (which means that you have two different names from one parameter – different in Ant and different in XSLT)
or doing test="$param = 'true'" instead of just test="$param".
Other option is using an XSLT processor which does the some automatic/magic casting for you
e.g. SaxonB 9.0 – but this magic stopped working in 9.1 (the magic behaviour is not based on the specification).

So here is a patch that adds support for several data types. Now you can write for example:

<param name="p6" expression="true" type="boolean"/>
<param name="p6" expression="128" type="int"/>
<param name="p6" expression="some text"/>

(default type is string to be compatible with current build.xml files)

And in XSL template you will get a property with appropriate data type.

These types are supported
	string
	boolean
	int
	long
	double
(more can be easily added if needed).

And also XPath expressions are supported – types:
	xpath:string
	xpath:boolean
	xpath:number
	xpath:node
	xpath:nodeset

So you can write e.g.:

<param name="p3" expression="64 * 64 div 128 + 10" type="xpath:number"/>

And in XSLT you will get numeric parameter with value 42.

For more examples please see attached files.

The XPath expression is evaluated on empty document, not on the transformed document, because it is not available yet.
Despite that you can compute something useful, call standard XPath functions and also access declared properties from Ant build.xml file.

n.b. if you use ${someParam} in the expression attribute it will by simply substituted by Ant,
but if you use $someParam here, the value will be evaluated by XPath processor.

I hope this patch will be useful for other users.
Comment 5 František Kučera <xkucf03/> 2013-06-28 17:33:32 UTC
Created attachment 30495 [details]
patch that adds support of several data types and XPath expressions in XSLT parameters
Comment 6 František Kučera <xkucf03/> 2013-06-28 17:36:03 UTC
Created attachment 30496 [details]
example of usage
Comment 7 Stefan Bodewig 2013-09-11 10:57:02 UTC
I've only got one not-so-small issue with your patch - you change a method signature in XSLTLiaison and thus may break existing implementations outside of Ant.  Right now I don't see a simple way to resolve this, other than introducing an additional interface with a new add method that was implemented by TraxLiaiison and checked by XSLTProcess before setting parameters.

Other than that I'd probably only suggest to use an EnumeratedAttribute for the new type attribute.

And of course I'd love to see your examples turned into documentation and tests ;-)
Comment 8 Matt Benson 2013-09-11 18:40:50 UTC
WRT the EnumeratedAttribute, I would say that since you're intending your changes to go to Ant's main codebase and not an antlib, you may as well use the Java 5 facilities available to you and use a true enum.
Comment 9 František Kučera <xkucf03/> 2013-10-15 16:12:52 UTC
Created attachment 30928 [details]
improved patch - adds XSLTLiaison4 interface for compatibility

Method addParam(String name, Object value) is now in XSLTLiaison4 interface, not in XSLTLiaison where is only original addParam(String name, String expression)
Comment 10 František Kučera <xkucf03/> 2013-10-15 18:49:29 UTC
Created attachment 30929 [details]
improved patch - ParamType implemented as a true enum

Param types are now upper-case and xpath ones contains _ instead of : character – e.g. XPATH_STRING
Comment 11 František Kučera <xkucf03/> 2013-10-18 18:56:38 UTC
Created attachment 30943 [details]
improved patch - adds documentation and tests
Comment 12 František Kučera <xkucf03/> 2013-10-18 18:59:28 UTC
Please review the latest patch:

 - XSLTLiaison4 interface for compatibility
 - ParamType implemented as a true enum
 - documentation
 - tests
Comment 13 Stefan Bodewig 2013-12-05 18:51:20 UTC
wonderful, your patch has become svn revision 1548237 - with one change, we have a no-@author-tag policy, so I removed the tag from XSLTLiaison4.

Thanks a lot for helping us close a ten year old ticket.