Apply-templates with-param problem / question

Here should go questions about transforming XML with XSLT and FOP.

Apply-templates with-param problem / question

Postby Stefan Messmer » Fri Jan 11, 2008 12:11 am

Hi all,
I observed a problem that seems to be a little strange. I defined a variable "date" with the following content:
<Cluster Name="Time stamp" NumElts="10">
<DBL Name="fractional second">0.13610</DBL>
<I32 Name="second">4</I32>
<I32 Name="minute">21</I32>
<I32 Name="hour">11</I32>
<I32 Name="day of month">4</I32>
<I32 Name="month">4</I32>
<I32 Name="year">2007</I32>
<I32 Name="day of week">4</I32>
<I32 Name="day of year">94</I32>
<I32 Name="DST">1</I32>
</Cluster>
The variable therefore contains a node set. Then I applied a template the following way:
<xsl:apply-template match=".">
<xsl:with-param name="my-date" select="$date"/>
</xsl:apply-template>

The template should replace an element <date/> with the actual date. The template looks the following:
<xsl:template match="date">
<xsl:param name="my-date"/>
.....
.....
</xsl:template>

Now the problem: Saxon 6.5, Xalan, Firefox, Opera will return an error, because the content of the variable my-date is a string and not a node set. Safari (xslt.lib) and Saxon 9 process this code as expected.

Which behavior is correct? Does anybody know a workaround?

Thanks for your help
Stefan Messmer
Stefan Messmer
 
Posts: 3
Joined: Thu Jan 10, 2008 11:49 pm
Location: Schaffhausen

Postby Dan » Fri Jan 11, 2008 3:46 pm

How did you defined the variable?
In the stylesheet, like the following, or it was given as a parameter to the XSLT processor?

Code: Select all
 
<xsl:variable name="date">       
        <Cluster Name="Time stamp" NumElts="10">
            <DBL Name="fractional second">0.13610</DBL>
            <I32 Name="second">4</I32>
            <I32 Name="minute">21</I32>
            <I32 Name="hour">11</I32>
            <I32 Name="day of month">4</I32>
            <I32 Name="month">4</I32>
            <I32 Name="year">2007</I32>
            <I32 Name="day of week">4</I32>
            <I32 Name="day of year">94</I32>
            <I32 Name="DST">1</I32>
        </Cluster>
</xsl:variable>


I have tried this and worked correctly:

Code: Select all
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>
   
    <xsl:variable name="date">       
        <Cluster Name="Time stamp" NumElts="10">
            <DBL Name="fractional second">0.13610</DBL>
            <I32 Name="second">4</I32>
            <I32 Name="minute">21</I32>
            <I32 Name="hour">11</I32>
            <I32 Name="day of month">4</I32>
            <I32 Name="month">4</I32>
            <I32 Name="year">2007</I32>
            <I32 Name="day of week">4</I32>
            <I32 Name="day of year">94</I32>
            <I32 Name="DST">1</I32>
        </Cluster>
    </xsl:variable>

   
    <xsl:template match="/">
        <xsl:apply-templates select="//date">
            <xsl:with-param name="my-date" select="$date"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="date">
        <xsl:param name="my-date"/>
        <out>
            <xsl:copy-of select="$my-date"/>
        </out>
    </xsl:template>
   
</xsl:stylesheet>


Can you give a complete sample? XSL, XML input, parameters?

Cheers,
Dan
Dan
 
Posts: 189
Joined: Mon Feb 03, 2003 10:56 am

Postby jkmyoung » Fri Jan 11, 2008 6:53 pm

Saxon 9 is a XSLT 2.0 processor is it not?
As such it would probably ignore these errors.

The behaviour that is correct is throwing the error.

If you're looking for compatibility, why not use the exsl:node-set extension?

Code: Select all
xmlns:exsl="http://exslt.org/common"
...
<xsl:with-param name="my-date" select="exsl:node-set($date)"/>


Another work-around. Encase in wrapper and use document function to retrieve.
The select attribute xpath ensures that these are treated as actual nodes.
Code: Select all
<my:mapping xmlns:my="internal">
<Cluster Name="Time stamp" NumElts="10">
<DBL Name="fractional second">0.13610</DBL>
<I32 Name="second">4</I32>
<I32 Name="minute">21</I32>
<I32 Name="hour">11</I32>
<I32 Name="day of month">4</I32>
<I32 Name="month">4</I32>
<I32 Name="year">2007</I32>
<I32 Name="day of week">4</I32>
<I32 Name="day of year">94</I32>
<I32 Name="DST">1</I32>
</Cluster>
</my:mapping>

<xsl:variable name="date" select="document('')//Cluster"/>
jkmyoung
 
Posts: 89
Joined: Mon Mar 06, 2006 10:13 pm

Postby jkmyoung » Fri Jan 11, 2008 6:55 pm

For further clarifications, the exsl namespace will work in saxon, not IE, and I don't know about firefox and opera.

(annoying that you can't edit posts)
jkmyoung
 
Posts: 89
Joined: Mon Mar 06, 2006 10:13 pm

Postby Stefan Messmer » Fri Jan 11, 2008 9:58 pm

Hi all

I have prepared an example. It should demonstrate my problem and it should be simple enough to understand quickly. First of all, the xml file:

Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl" ?>
<data>
   <Cluster Name="test-date" NumElts="10">
      <DBL Name="fractional second">0.13610</DBL>
      <I32 Name="second">4</I32>
      <I32 Name="minute">21</I32>
      <I32 Name="hour">11</I32>
      <I32 Name="day of month">4</I32>
      <I32 Name="month">4</I32>
      <I32 Name="year">2007</I32>
      <I32 Name="day of week">4</I32>
      <I32 Name="day of year">94</I32>
      <I32 Name="DST">1</I32>
   </Cluster>
   <String Name="rope-name">Zugseil</String>
   <String Name="test-advice">Seilverordnung</String>
   <String Name="installation-name-nickname">Musteranlage</String>
   <Section Name="section-1" Printflag="true">
      <Textblock Name="Entspricht Seilverordnung">Das <rope-name/> der Anlage
         <installation-name-nickname/> entsprach zum Zeitpunkt der Prüfung am <test-date
            format="short"/> in den geprüften Bereichen den Anforderungen der
         <test-advice/>.</Textblock>
      <Section Name="subsection-11" Printflag="true">
         <Textblock Name="Entspricht Seilverordnung">Das <rope-name/> der Anlage
            <installation-name-nickname/> entsprach zum Zeitpunkt der Prüfung am <test-date
               format="abbreviated"/> in den geprüften Bereichen den Anforderungen der
            <test-advice/>.</Textblock>
         <Textblock Name="Entspricht Seilverordnung">Das <rope-name/> der Anlage
            <installation-name-nickname/> entsprach zum Zeitpunkt der Prüfung am <test-date
               format="long"/> in den geprüften Bereichen den Anforderungen der
            <test-advice/>.</Textblock>
      </Section>
         <Textblock Name="Entspricht Seilverordnung">Das <rope-name/> der Anlage
            <installation-name-nickname/> entsprach zum Zeitpunkt der Prüfung am <test-date
               format="short"/> in den geprüften Bereichen den Anforderungen der
            <test-advice/>.</Textblock>
   </Section>
</data>


The corresponding stylesheet is as follows:

Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="data">
   <xsl:variable name="test-date" select="Cluster[@Name='test-date']"/>
   <xsl:variable name="test-advice" select="String[@Name='test-advice']"/>
   <xsl:variable name="rope-name" select="String[@Name='rope-name']"/>
   <xsl:variable name="installation-name-nickname" select="String[@Name='installation-name-nickname']"/>
   <htmL>
      <title>Report</title>
      <body>
         <xsl:for-each select="//Textblock"><p>
            <xsl:apply-templates select=".">
               <xsl:with-param name="my-date" select="$test-date"/>
               <xsl:with-param name="my-advice" select="$test-advice"/>
               <xsl:with-param name="my-rope-name" select="$rope-name"></xsl:with-param>
               <xsl:with-param name="my-installation-name" select="$installation-name-nickname"></xsl:with-param>
            </xsl:apply-templates></p>
         </xsl:for-each>
      </body>
   </htmL>
</xsl:template>
   <xsl:template match="test-advice">
      <xsl:param name="my-advice"/>
      <xsl:value-of select="$my-advice"/>
   </xsl:template>
   <xsl:template match="rope-name">
      <xsl:param name="my-rope-name"/>
      <xsl:value-of select="$my-rope-name"/>
   </xsl:template>
   <xsl:template match="installation-name-nickname">
      <xsl:param name="my-installation-name"/>
      <xsl:value-of select="$my-installation-name"/>
   </xsl:template>
   <xsl:template match="test-date">
      <xsl:param name="my-date"/>
      <xsl:variable name="format" select="@format"/>
      <xsl:choose>
         <xsl:when test="$format = 'short'">
            <xsl:value-of select="$my-date/I32[@Name='day of month']"/>.<xsl:value-of
               select="$my-date/I32[@Name='month']"/>.<xsl:value-of
                  select="$my-date/I32[@Name='year']"/>
         </xsl:when>
         <xsl:when test="$format = 'abbreviated'">
            <xsl:value-of select="$my-date/I32[@Name='day of month']"/>.<xsl:choose>
               <xsl:when test="$my-date/I32[@Name='month']=1"> Jan </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=2"> Feb </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=3"> Mar </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=4"> Apr </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=5"> Mai </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=6"> Jun </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=7"> Jul </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=8"> Aug </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=9"> Sep </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=10"> Okt </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=11"> Nov </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=12"> Dez </xsl:when>
               <xsl:otherwise>(Fehler im Datum)</xsl:otherwise>
            </xsl:choose><xsl:value-of select="$my-date/I32[@Name='year']"/>
         </xsl:when>
         <xsl:when test="$format = 'long'">
            <xsl:value-of select="$my-date/I32[@Name='day of month']"/>.<xsl:choose>
               <xsl:when test="$my-date/I32[@Name='month']=1"> Januar </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=2"> Februar </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=3"> März </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=4"> April </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=5"> Mai </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=6"> Juni </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=7"> Juli </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=8"> August </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=9"> September </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=10"> Oktober </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=11"> November </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=12"> Dezember </xsl:when>
               <xsl:otherwise>(Fehler im Datum)</xsl:otherwise>
            </xsl:choose><xsl:value-of select="$my-date/I32[@Name='year']"/>
         </xsl:when>
         <xsl:otherwise>(Nicht unterstütztes Format &quot;<xsl:value-of select="$format"
         />&quot;)</xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>


I hope this helps to clarify the problem.

Best regards
Stefan Messmer[/code]
Stefan Messmer
 
Posts: 3
Joined: Thu Jan 10, 2008 11:49 pm
Location: Schaffhausen

Postby Dan » Mon Jan 14, 2008 1:55 pm

Changing the stylesheet version to "1.1" and changing the apply-templates select value from "." to "./*" seems to fix the problem when using Saxon 6, Xalan, Firefox (I have not tested IE and Opera):

Code: Select all
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1">
........
                    <xsl:apply-templates select="./*">


More reading about the node-sets here:http://www.xml.com/pub/a/2003/07/16/nodeset.html
Dan
 
Posts: 189
Joined: Mon Feb 03, 2003 10:56 am

Postby Stefan Messmer » Mon Jan 14, 2008 7:11 pm

Hi all,

I found another solution. The stylesheet is attached below. :D

Many thanks for your help
Stefan Messmer


Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:template match="data">
      <xsl:variable name="test-date" select="Cluster[@Name='test-date']"/>
      <xsl:variable name="test-advice" select="String[@Name='test-advice']"/>
      <xsl:variable name="rope-name" select="String[@Name='rope-name']"/>
      <xsl:variable name="installation-name-nickname"
         select="String[@Name='installation-name-nickname']"/>
      <html>
         <title>Report</title>
         <body>
            <xsl:for-each select="//Textblock">
               <p>
                  <xsl:apply-templates>
                     <xsl:with-param name="my-date" select="$test-date"/>
                     <xsl:with-param name="my-advice" select="$test-advice"/>
                     <xsl:with-param name="my-rope-name" select="$rope-name"/>
                     <xsl:with-param name="my-installation-name" select="$installation-name-nickname"/>
                  </xsl:apply-templates>
               </p>
            </xsl:for-each>
         </body>
      </html>
   </xsl:template>
   <xsl:template match="test-advice">
      <xsl:param name="my-advice"/>
      <xsl:value-of select="$my-advice"/>
   </xsl:template>
   <xsl:template match="rope-name">
      <xsl:param name="my-rope-name"/>
      <xsl:value-of select="$my-rope-name"/>
   </xsl:template>
   <xsl:template match="installation-name-nickname">
      <xsl:param name="my-installation-name"/>
      <xsl:value-of select="$my-installation-name"/>
   </xsl:template>
   <xsl:template match="test-date">
      <xsl:param name="my-date"/>
      <xsl:variable name="format" select="@format"/>
      <xsl:choose>
         <xsl:when test="$format = 'short'">
            <xsl:value-of select="$my-date/I32[@Name='day of month']"/>.<xsl:value-of
               select="$my-date/I32[@Name='month']"/>.<xsl:value-of select="$my-date/I32[@Name='year']"/>
         </xsl:when>
         <xsl:when test="$format = 'abbreviated'">
            <xsl:value-of select="$my-date/I32[@Name='day of month']"/>.<xsl:choose>
               <xsl:when test="$my-date/I32[@Name='month']=1"> Jan </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=2"> Feb </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=3"> Mar </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=4"> Apr </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=5"> Mai </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=6"> Jun </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=7"> Jul </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=8"> Aug </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=9"> Sep </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=10"> Okt </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=11"> Nov </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=12"> Dez </xsl:when>
               <xsl:otherwise>(Fehler im Datum)</xsl:otherwise>
            </xsl:choose><xsl:value-of select="$my-date/I32[@Name='year']"/>
         </xsl:when>
         <xsl:when test="$format = 'long'">
            <xsl:value-of select="$my-date/I32[@Name='day of month']"/>.<xsl:choose>
               <xsl:when test="$my-date/I32[@Name='month']=1"> Januar </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=2"> Februar </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=3"> März </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=4"> April </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=5"> Mai </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=6"> Juni </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=7"> Juli </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=8"> August </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=9"> September </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=10"> Oktober </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=11"> November </xsl:when>
               <xsl:when test="$my-date/I32[@Name='month']=12"> Dezember </xsl:when>
               <xsl:otherwise>(Fehler im Datum)</xsl:otherwise>
            </xsl:choose><xsl:value-of select="$my-date/I32[@Name='year']"/>
         </xsl:when>
         <xsl:otherwise>(Nicht unterstütztes Format &quot;<xsl:value-of select="$format"
            />&quot;)</xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>
Stefan Messmer
 
Posts: 3
Joined: Thu Jan 10, 2008 11:49 pm
Location: Schaffhausen

Postby jkmyoung » Mon Jan 14, 2008 8:01 pm

Another alternative to wieldly nested choose clauses is this little trick:

<my:mapping xmlns:my="internal">
<month short="1" abr="Jan" long="Januar" />
<month short="2" abr="Feb" long="Februar" />
<month short="3" abr="Mar" long="März" />
<month short="4" abr="Apr" long="April" />
<month short="5" abr="Mai" long="Mai" />
<month short="6" abr="Jun" long="Juni" />
<month short="7" abr="Jul" long="Juli" />
<month short="8" abr="Aug" long="August" />
<month short="9" abr="Sep" long="September" />
<month short="10" abr="Okt" long="Oktober" />
<month short="11" abr="Nov" long="November" />
<month short="12" abr="Dez" long="Dezember" />
</my:mapping>
<xsl:variable name="monthNum" select="$my-date/I32[@Name='month']"/>

Then in your abbreviated choose clause could have something like
<xsl:value-of select="document('')//month[@short=$monthNum]/@abr"/>

long choose clause:
<xsl:value-of select="document('')//month[@short=$monthNum]/@long"/>

This may be of use to you.
jkmyoung
 
Posts: 89
Joined: Mon Mar 06, 2006 10:13 pm


Return to XSLT and FOP

Who is online

Users browsing this forum: No registered users and 0 guests

cron