I have declared a variable in my .xsl file. Now I want to update the older value with new value. For example:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<Document>
<xsl:variable name="topLevelHeadings" select = "//w:body/w:p[w:pPr[w:pStyle[@w:val='Heading1']]]"/>
<xsl:variable name="beforeHeading" select="false()"/>
<xsl:choose>
<xsl:when test="$beforeHeading">
<xsl:apply-templates select="//w:body/w:p">
<xsl:with-param name="scope" select="count(//w:body/child::*)-1"/>
</xsl:apply-templates>
</xsl:when>
<xsl:when test="$topLevelHeadings">
<xsl:variable name="beforeHeading" select="true()"/>
<xsl:apply-templates select="$topLevelHeadings">
<xsl:with-param name="scope" select="count(//w:body/child::*)-1"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="//w:body/w:p[w:r[w:t]]">
<xsl:with-param name="scope" select="count(//w:body/child::*)-1"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</Document>
</xsl:template>
<xsl:template match="w:body/w:p">
<xsl:param name = "scope"/>
<xsl:variable name ="index" select="count(preceding-sibling::*)"/>
<xsl:if test = "$index <= $scope">
<Paragraph>
<xsl:attribute name="index">
<xsl:value-of select="$index" />
</xsl:attribute>
<xsl:apply-templates select=".//w:r/w:t"/>
</Paragraph>
</xsl:if>
</xsl:template>
<xsl:template match="w:t">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="w:body/w:p">
<xsl:param name = "scope"/>
<xsl:variable name ="index" select="count(preceding-sibling::*)"/>
<xsl:if test = "$index <= $scope">
<Paragraph>
<xsl:attribute name="index">
<xsl:value-of select="$index" />
</xsl:attribute>
<xsl:apply-templates select=".//w:r/w:t"/>
</Paragraph>
</xsl:if>
</xsl:template>
<xsl:template name="get-para-index">
<xsl:param name="node"/>
<xsl:value-of select="count($node/preceding-sibling::*)"/>
</xsl:template>
<xsl:template match="//w:body/w:p[w:pPr[w:pStyle]]">
<xsl:param name = "scope"/>
<xsl:variable name="currIndex" select="count(preceding-sibling::*)"/>
<xsl:if test="$currIndex <= $scope">
<!-- Get current heading value -->
<xsl:variable name="currHeading" select="./w:pPr/w:pStyle/@w:val"/>
<!-- Heading tag -->
<xsl:element name="{$currHeading}">
<!-- Get heading text -->
<Title>
<xsl:attribute name ="index">
<xsl:value-of select="$currIndex"/>
</xsl:attribute>
<xsl:apply-templates select=".//w:r/w:t"/>
</Title>
<!-- Get the scope of paragraphs inside this heading -->
<xsl:variable name="nextHeading" select="following-sibling::w:p[w:pPr[w:pStyle[@w:val]]][1]"/>
<xsl:variable name="paraScope">
<xsl:choose>
<xsl:when test="$nextHeading">
<xsl:call-template name="get-para-index">
<xsl:with-param name="node" select="$nextHeading"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="count(//w:body/child::*)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Handle paragraphs under this heading -->
<xsl:apply-templates select="following-sibling::w:p[//w:r and not(w:pPr[w:pStyle])]">
<xsl:with-param name="scope" select="$paraScope"/>
</xsl:apply-templates>
<!-- Get the first heading after current node at the same level -->
<xsl:variable name="nextSibling" select="following-sibling::w:p[w:pPr[w:pStyle[@w:val=$currHeading]]][1]"/>
<!-- Get its index -->
<xsl:variable name="nextSiblingIndex">
<xsl:choose>
<xsl:when test="$nextSibling">
<xsl:call-template name="get-para-index">
<xsl:with-param name="node" select="$nextSibling"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$scope"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Set the scope of this node - this will be the smaller of nextSiblingIndex and current scope -->
<xsl:variable name="currScope">
<xsl:choose>
<xsl:when test="$nextSiblingIndex < $scope">
<xsl:value-of select="$nextSiblingIndex"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$scope"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="nextHead" select="concat('Heading', number(substring-after($currHeading, 'Heading'))+1)"/>
<!-- Get a list of child nodes (headings) for the current node -->
<xsl:variable name="nextLevelHeadings" select="following-sibling::w:p[w:pPr[w:pStyle[@w:val=$nextHead]]]"/>
<!-- Apply recursively for next level headings within the scope -->
<xsl:apply-templates select="$nextLevelHeadings">
<xsl:with-param name="scope" select="$currScope"/>
</xsl:apply-templates>
<!-- Close heading tag -->
</xsl:element>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I second @scunliffe - if $var exists but is empty, test="$var" will still return true. However, you may need to write it test="not($var = '')" if you are using earlier versions of XSL.
In XSLT, variable are 'immutable' and cannot be changed once set. So if you have initially set them to '0' then they stay set to '0'. All your code is trying to do is re-define new variables with the same name. As the new variables are in the same scope as the existing variables, an error occurs.
The difference is that the value of an xsl:param could be set outside the context in which it is declared.
If it happens that you need such a behavior in a transform, it means that probably you have to change the overall "design" of it. It's also hard to get what you are trying to do wihtout showing your input document and the wanted output.
Because you can't update variables, you have to rethink your code. The pattern (that I'm able to imagine) closest to your request is something like this:
<xsl:template match="/">
<xsl:variable name="topLevelHeadings" select="//w:body/w:p
[w:pPr[w:pStyle[@w:val='Heading1']]]"/>
<xsl:variable name="beforeHeading">
<xsl:choose>
<xsl:when test="$topLevelHeadings">
<xsl:value-of select="true()"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="false()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- your choose staff -->
<!-- for instance -->
<xsl:if test="$beforeHeading='true'">
<xsl:message>pass</xsl:message>
</xsl:if>
</xsl:template>
You can't. XSLT is a functional programming language so variables cannot be modified. Use recursion to do what you want instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With