Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: [xsl] setting up tables differently based on existance of xml tags. (static variables, recursion, templates, and intrigue)

From: Geert Josten <Geert.Josten@----------->
To:
Date: 12/1/2004 6:24:00 PM
Hi Robert,



...



   <xsl:when test="value and not($col)">
       <fo:table-row>
           <fo:table-cell><xsl:value-of select="title"/></fo:table-cell>
           <fo:table-cell>text</fo:table-cell>
           <xsl:variable name="col" select="'true'"/>
   </xsl:when>
   <xsl:when test="value and $col">
           <fo:table-cell><xsl:value-of select="title"/></fo:table-cell>
           <fo:table-cell>text</fo:table-cell>
        </fo:table-row>
        <xsl:variable name="col" select="''"/>
   </xsl:when>

...



This obviously will not work, because XSLT does not allow variables to
be reassigned.

Worse: this violates the well-formned requirement of XML.



> After reading extensively from O'Reilly's XSLT book
and the w3c specs for XSLT and XPath, I decided I could achive my goal
with recursive template matches.  Here is what I arrived at:

/----------------------------------------------------------------------------------------<xsl:stylesheet . . .>
   <xsl:template match="document">
. . .
        <fo:table-body>
            <xsl:apply-templates select="field[1]">
        </fo:table-body>
. . .
   </xsl:template> <!-- end template match="document" -->
   <xsl:template match="field">
       <xsl:choose>
           <!-- When current <field> has <value/> and next <field>
has <value/> -->
           <xsl:when test="value and following-sibling::field[1]/value">
               <fo:table-row>
                   <fo:table-cell>
                       <!-- current title -->
                       <fo:block><xsl:value-of select="title"/></fo:block>
                   </fo:table-cell>
                   <fo:table-cell>
                       <fo:block>text</fo:block>
                   </fo:table-cell>
                   <fo:table-cell>
                       <!-- next title -->
                       <fo:block><xsl:value-of
select="following-sibling::field[1]/title"/></fo:block>
                   </fo:table-cell>
                   <fo:table-cell>
                       <fo:block>text</fo:block>
                   </fo:table-cell>
               </fo:table-row>
               <!-- use this template for the next element (after the
one previously referred
                     to as 'next'. omitting the final '[1]' will
cause this template to be processed
                     remaining <field>, which results in very long
files with lots of stuff i don't
                     want. -->
               <xsl:apply-templates
select="following-sibling::field[position() &gt; 1][1]"/>

Err, why not use "following-sibling::field[2]"? :-)



           </xsl:when>
           <!-- if not. . . -->
           <xsl:otherwise>
               <fo:table-row>
                   <fo:table-cell>
                       <fo:block><xsl:value-of select="title"/></fo:block>
                   </fo:table-cell>
                   <fo:table-cell number-columns-spanned="3">
                       <fo:block>other text</fo:block>
                   </fo:table-cell>
               </fo:table-row>
               <!-- use this template for the next element. again,
don't omit '[1]'. -->
               <xsl:apply-templates select="following-sibling::field[1]"/>
           </xsl:otherwise>
       </xsl:choose>
   </xsl:template>
\------------------------------------------------------------------------------------/

This works great.  Based on my understanding of the XSLT parsers, this
is pretty memory intensive, as applying "following-sibling::field[1]"
actually passes the remaining <field> nodes in <document> every time,
leaving a lot of stuff in the stack. Is that correct?

I'm not sure what you mean by this, but "following-sibling::field[1]" results in a node-set with 
either one or zero elements named field. So for at most one element a new apply-templates is being 
issued.



It is true that when you have n field siblings, you potentially build up a stack of n 
apply-templates calls, but it isn't so that all field siblings are stacked each time. There is no 
need for this. The field nodes are in the source tree and are always available. The things that do 
need to be cached are the pointer to the current node, the current context list (here in most cases 
a node-set of only one field node) and variables if you would be using them...



At any rate, any ideas on a better way to do this?  (Other than a SAX
parsing of the XML with a few variables and leaving an extra node in
select <field>s.)

No, I think it is perfectly sound already... except for the [position() > 1][1], you can simply 
replace that by [2]...



G.


transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent