You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-users@xalan.apache.org by Ralph Brenner <rb...@openharbor.com> on 2004/06/29 20:53:30 UTC

RE: Cannot compile stylesheet that passes Java object as template par ameter

There is a typo in the second stylesheet example in my previous email.  In
the call-template element, the enclosed element should be <xsl:with-param
... />  I had incorrectly listed it without the "with-", as <xsl:param ...
/>.  Sorry about that.  The snippet of code should read:
 
        <xsl:call-template name="passObject"> 
            <xsl:with-param name="calAsObject" 
                select="$calAsObject"/> 
        </xsl:call-template>

Anyway, the end result is that still the stylesheet will not compile:

Compiler errors:
  Cannot convert data-type 'java.lang.Object' to 'reference'.

Regards,
   Ralph


-----Original Message-----
From: Ralph Brenner [mailto:rbrenner@openharbor.com] 
Sent: Monday, June 28, 2004 4:56 PM
To: 'Santiago Pericas-Geertsen'
Cc: 'xalan-j-users@xml.apache.org'
Subject: RE: Cannot compile stylesheet that passes Java object as template
par ameter

Hi again, Santiago, 
I've tried another approach, to cast a Java GregorianCalendar to a generic
Object, and then cast it back to its original type.  This works within a
single template, as shown here:
  
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0" 
    xmlns:java="http://xml.apache.org/xalan/java" 
    xmlns:xsltc="http://xml.apache.org/xalan/xsltc"> 
    <xsl:template match="/"> 
        <xsl:variable name="javaCal" 
            select="java:java.util.GregorianCalendar.new()"/> 
        <xsl:variable name="calAsObject" 
            select="xsltc:cast('java.lang.Object', $javaCal)"/> 
        <xsl:variable name="reconstitutedJavaCal" 
            select="xsltc:cast('java.util.GregorianCalendar',
$calAsObject)"/> 
        reconstituted calendar object: 
        <xsl:value-of
select="java:toString(java:getTime($reconstitutedJavaCal))"/> 
    </xsl:template> 
</xsl:stylesheet> 

However, when I try to pass the generic object to another template... I can
pass the object, but an error is generated when I try to cast it back to its
original type:
ERROR:  'java.lang.String' 
(Location of error unknown)XSLT Error
(javax.xml.transform.TransformerException): java.lang.ClassCastException:
java.lang.String

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0" 
    xmlns:java="http://xml.apache.org/xalan/java" 
    xmlns:xsltc="http://xml.apache.org/xalan/xsltc"> 
    <xsl:template match="/"> 
        <xsl:variable name="javaCal" 
            select="java:java.util.GregorianCalendar.new()"/> 
        <xsl:variable name="calAsObject" 
            select="xsltc:cast('java.lang.Object', $javaCal)"/> 
        <xsl:call-template name="passObject"> 
            <xsl:param name="calAsObject" 
                select="$calAsObject"/> 
        </xsl:call-template> 
    </xsl:template> 
    <xsl:template name="passObject"> 
        <xsl:param name="calAsObject"/> 
        <xsl:variable name="reconstitutedJavaCal" 
            select="xsltc:cast('java.util.GregorianCalendar',
$calAsObject)"/> 
        reconstituted in called template: 
        <xsl:value-of
select="java:toString(java:getTime($reconstitutedJavaCal))"/> 
    </xsl:template> 
</xsl:stylesheet> 

It would be great if a future release would support the compilation of
stylesheets which pass java objects as parameters.  In the meantime, I'm
using a different approach: I am able to serialize a
javax.xml.transform.Templates object and then read that back from the file
system.  The downside is that there is very little improvement over just
running the stylesheet in the interpreter mode... so I'd prefer compiling to
a translet.  One question/comment on this topic:  in order for the Templates
serialization to work, there are a couple of Xalan classes that need to be
updated to implement the java.io.Serializable interface:

org.apache.xalan.extensions.ExtensionNamespacesManager 
org.apache.xalan.extensions.ExtensionNamespaceSupport 

There is already a bug opened, but this update has not yet been performed. 
See: 
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22891 
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=19400 

Any possibility of getting those two files' officially updated in the
meantime? 

Thanks, 
   Ralph 

-----Original Message----- 
From: Santiago Pericas-Geertsen [mailto:Santiago.Pericasgeertsen@Sun.COM] 
Sent: Friday, June 25, 2004 7:50 AM 
To: Ralph Brenner 
Cc: 'xalan-j-users@xml.apache.org' 
Subject: RE: Cannot compile stylesheet that passes Java object as template
par ameter 
Ralph, 
Yes, that is a known issue. The problem is that XSLTC implements most of its
type checking statically, and there are some problems with xsl:param and
non-XSLT types. In particular, the type of a parameter cannot be determine
statically in XSLT, which means that if you pass a GregorianCalendar as a
parameter to a template, its type will be subsumed to Object. Consequently,
you won't be able to call any useful methods on that param unless you
downcast it (which is possible using an XSLTC extension, but it is of course
not portable). 
In summary, even if the type checker is changed to allow arbitrary
conversions to Reference (i.e. the type a parameter) this may still not be
the end of the story. However, if you find it useful, it is a very simple
change. See attachment for an example of how to use xsltc:cast().
-- Santiago 
On Thu, 2004-06-24 at 16:49, Ralph Brenner wrote: 
Hi Santiago, 
  
Thanks for the fix!  It does indeed address the problem for Java *String*
objects.  
However, there still exists a problem for other types of Java objects.  For
example, 
the following XSLT processes fine with org.apache.xalan.xslt.Process but
generates 
an error when I try to compile it with
org.apache.xalan.xsltc.cmdline.Compile: 
  
     Cannot convert data-type 'java.util.GregorianCalendar' to 'reference'. 
  
The goal is to be able to pass any Java object to a template and then be
able to 
execute methods against it. 
  
  
EXAMPLE XSLT: 
------------- 
  
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:java="http://xml.apache.org/xalan/java" 
    version="1.0"> 
  
    <xsl:template match="/"> 
        <xsl:variable 
            name="javaObject" 
            select="java:java.util.GregorianCalendar.new()"/> 
        <xsl:call-template name="aTemplate"> 
            <xsl:with-param name="javaObject" select="$javaObject"/> 
        </xsl:call-template> 
    </xsl:template> 
  
    <xsl:template name="aTemplate"> 
        <xsl:param name="javaObject"/> 
        <xsl:value-of select="java:getTime($javaObject)"/> 
    </xsl:template> 
</xsl:stylesheet> 
  
  
Regards, 
   Ralph 
  
  
-----Original Message----- 
From: Santiago Pericas-Geertsen [mailto:Santiago.Pericasgeertsen@Sun.COM] 
Sent: Thursday, June 24, 2004 9:16 AM 
To: Ralph Brenner 
Cc: 'xalan-j-users@xml.apache.org' 
Subject: Re: Cannot compile stylesheet that passes Java object as template
par ameter 
  
Ralph, 
Please try the current CVS. A related bug has been fixed today. Hope it
works for you. 
-- Santiago 
On Wed, 2004-06-23 at 19:22, Ralph Brenner wrote: 
I am unable to compile a stylesheet that passes a Java object as a parameter
to a template.  For example, when trying to pass a Java String, I get the
following error:
    Cannot convert data-type 'java.lang.String' to 'reference'. 
However, I am able to successfully process the template when I do not
compile it. 
e.g. this does not work: 
   java org.apache.xalan.xsltc.cmdline.Compile example.xsl 
But this works: 
   java org.apache.xalan.xslt.Process -XSL example.xsl 
Here is an example XSL file which illustrates the problem: 
example.xsl: 
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:java="http://xml.apache.org/xalan/java" 
    version="1.0"> 
    
    <xsl:template match="/"> 
        <xsl:variable 
            name="javaString" 
            select="java:java.lang.String.new('java variable test')"/> 
        <xsl:call-template name="aTemplate"> 
            <xsl:with-param name="javaString" select="$javaString"/> 
        </xsl:call-template> 
    </xsl:template> 
    <xsl:template name="aTemplate"> 
        <xsl:param name="javaString"/> 
        <xsl:value-of select="$javaString"/> 
    </xsl:template> 
</xsl:stylesheet>