xsl-list
[Top] [All Lists]

Re: [xsl] Dynamic numbering of lists in xslt

2007-01-10 10:26:48
Hello All:

I finally got this to work with <xsl:number>.Thanks a lot! This works
great for XSLT.

I am trying to use a similar logic for another module that I am
working on. Here, there are two parameters are passed adhoc thru the
style sheet, and based on these values, I need to use a numberd list
but this time using XSLFO and not XSLT. (I am using renderx as the FO
processor)

I have two parameters: place and time which are passed adhoc to the
style sheet. My input
xml is
<travel1>
<location
<place>NY<place>
<time>EST</time>
</location>
   <travel2>
<location
<place>CaL<place>
<time>PST</time>
</location>
</travel2>
</travel1>
<travel1>
<location
<place>Chi<place>
<time>CST</time>

</location>
</travel1>
<travel1>
<location
<place>NY<place>
<time>EST</time>

</location>
</travel1>
the place and time are passed adhoc to the style sheet. So if place=NY
and time=EST, then the first <travel1> node and the third<travel1>
node should be displayed in a sequenctial order. I am using
fo:list-item-block and <xsl:number> to number the nodes.
My desired output is:
1. NY, EST
2. NY, EST

But since my logic is only on the style sheet and the XML still
contains all the three <travel1> nodes, i get an output like this:

1. NY, EST
3. NY, EST.

so my XSLFO is:

<xsl:template match="travel1">

<xsl:choose>

<xsl:when test=".//location">
<xsl:if test=".//location/place=$place and .//location/time=$time">
<fo:list-block space-before="6pt" space-before.conditionality="retain">
        <fo:list-item>
                <fo:list-item-label end-indent="label-end()">
                        <fo:block>
                                <xsl:number format="1"/>
                        </fo:block>
                </fo:list-item-label>
                <fo:list-item-body start-indent="body-start()" end-indent="0pt">
                        <fo:block>
                                <xsl:apply-templates/>
                        </fo:block>
                </fo:list-item-body>
        </fo:list-item>
</fo:list-block>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>

This template is repeated for elment <travel2> as well. <travel2> is a
child of <travel1>.

So, the  <fo:list-item>.

<fo:list-block space-before="6pt" space-before.conditionality="retain">
        <xsl:if test="location/environment=$environment and 
location/company=$company">
                <fo:list-item>
                        <fo:list-item-label end-indent="label-end()">
                                <fo:block>
                                        <xsl:number format="1"/>
                                </fo:block>
                        </fo:list-item-label>
                        <fo:list-item-body start-indent="body-start()" 
end-indent="0pt">
                                <fo:block>
                                        <xsl:apply-templates/>
                                </fo:block>
                        </fo:list-item-body>
                </fo:list-item>
        </xsl:if>
</fo:list-block>

does not give a sequential list, and skips the nodes in between that
do not match the criteria.

Please let me know if any of this is achievable in XSLFO using renderx.


On 1/9/07, Abel Braaksma <abel(_dot_)online(_at_)xs4all(_dot_)nl> wrote:
David Carlisle wrote:

>>    <xsl:number />  <!-- will only count the matches consecutively -->
>
> Nope, it will number according to the input tree (but the advice to use
> templates rather than a xsl:choose stricture is good)

You are right, of course. Using position(), you can change this behavior
through the apply-templates. Using the input from the OP, and my
approach, the following is a way to do it (using xslt 2 for ease of use
and not needing an input doc, call it on itself)

<xsl:stylesheet
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

    <xsl:output indent="yes"/>

    <xsl:variable name="source">
        <chapter1>
            <section>first section</section>
        </chapter1>
        <chapter1>
            <section>second section</section>
        </chapter1>
        <chapter1>
            <section>third section</section>
        </chapter1>
        <chapter1>
            <section>fourth section</section>
        </chapter1>
    </xsl:variable>

    <xsl:template match="/">
        <xsl:apply-templates
            select="$source/chapter1[not(section = 'second section')]" />
    </xsl:template>

    <xsl:template match="chapter1">
        <chap>
            <xsl:value-of select="concat(position(), '. ', section)" />
        </chap>
    </xsl:template>

</xsl:stylesheet>

Output:
<chap>1. first section</chap>
<chap>2. third section</chap>
<chap>3. fourth section</chap>


However, if the select-statement becomes more complex, other approaches
may be better (not meaning xsl:choose). In addition, if XSLT 2.0 were an
option, the select-attribute could be used to achieve the same goal.

If Saxon extensions can be used, an easy (but unwanted) quick fix is to
use saxon's assignable variables.

-- Abel

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--