XSLT passing variables inside nested for-each loops

1.7k views Asked by At

I am fairly new at this and I am not sure if it is possible to do what I want to achieve here. I have 3 for-each loops that stores a number for every chapter, section and paragraph. I want to get that stored number from the previous for-each loop and display it in the nested loop, but I can't get it to work.

<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet 
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
            <html>
                <head>
                    <title>Table of Contents, Chapter 3</title>
                </head>

                <body>
                    <xsl:for-each select="chapter">
                        <tr>
                            <xsl:variable name="capnr">
                                <xsl:number value="3" format="1. "/>
                            </xsl:variable>
                            <xsl:value-of select="$capnr"/>
                            <xsl:value-of select="@title"/>
                        </tr>
                        <br />

                        <xsl:for-each select="section">
                            <tr>
                                <xsl:variable name="secnr">
                                    <xsl:number format="1. "/>
                                </xsl:variable>
                                <xsl:value-of select="$capnr"/>
                                <xsl:value-of select="$secnr"/>
                                <xsl:value-of select="@title"/>
                            </tr>
                            <br />

                            <xsl:for-each select="paragraph">
                                <tr>
                                    <xsl:variable name="parnr">
                                        <xsl:number format="1 "/>
                                    </xsl:variable>
                                    <xsl:value-of select="$capnr"/>
                                    <xsl:value-of select="$secnr"/>
                                    <xsl:value-of select="$parnr"/>
                                    <xsl:value-of select="@title"/>
                                </tr>
                            </xsl:for-each>
                            <br />

                        </xsl:for-each>

                    </xsl:for-each>

                </body>

            </html>

        </xsl:template>


    </xsl:stylesheet>

XML:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="ToC-3.xsl"?>
<chapter title="Chapter 3: Expressions">

<section title="Variables">
<paragraph title="Simple variables"></paragraph>
<paragraph title="Text variables"></paragraph>
<paragraph title="Remote identifiers"></paragraph>
</section>

<section title="The logical operators">
<paragraph title="Precedence of Boolean operators"></paragraph>
</section>

<section title="Designational expressions">
</section>

</chapter>
1

There are 1 answers

2
AudioBubble On BEST ANSWER

Without more details on the input and output, this should work. Of note is that the variable name is on the root, to allow all templates to access it. but since there appears to be one XSl per chapter this shouldn't be a problem.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:variable name="capnr">
           <xsl:number value="3" format="1."/>
        </xsl:variable>    
    <xsl:template match="/">
        <html>
                <head>
                    <title>Table of Contents, Chapter 3</title>
                </head>

                <body>
                    <xsl:apply-templates/>
                </body>
        </html>
    </xsl:template>

    <xsl:template match="chapter">
                             <h1>        
            <xsl:value-of select="$capnr"/>
            <xsl:value-of select="@title"/>
        </h1>
        <ol><xsl:apply-templates/></ol>
    </xsl:template>

    <xsl:template match="section">
        <li>
            <xsl:value-of select="$capnr"/>
            <xsl:value-of select="position()"/>
            <xsl:text> - </xsl:text>
            <xsl:value-of select="@title"/>
            <ol><xsl:apply-templates/></ol>
        </li>
    </xsl:template>

    <xsl:template match="paragraph">
        <li>
            <xsl:value-of select="$capnr"/>
            <xsl:value-of select="count(../preceding-sibling::*) + 1"/>
            <xsl:text>.</xsl:text>
            <xsl:value-of select="position()"/>
            <xsl:text> - </xsl:text>
            <xsl:value-of select="@title"/>
            <ol><xsl:apply-templates/></ol>
        </li>
    </xsl:template>
</xsl:stylesheet>

The above when applied to the given input XMl gives:

<html>
<head>
<title>Table of Contents, Chapter 3</title>
</head>
<body>
<h1>3.Chapter 3: Expressions</h1>
<ol><li>3.1 - Variables<ol><li>3.1.1 - Simple variables<ol></ol>
</li>
<li>3.1.2 - Text variables<ol></ol>
</li>
<li>3.1.3 - Remote identifiers<ol></ol>
</li>
</ol>
</li>
<li>3.2 - The logical operators<ol><li>3.2.1 - Precedence of Boolean operators<ol></ol>
</li>
</ol>
</li>
<li>3.3 - Designational expressions<ol></ol>
</li>
</ol>
</body>
</html>