Search

I’ve been trying to figure this out for an hour and a half and all the sure-fire ways to do this I can find do not work.

Basically, I need to create a parameter which will initially be set to 0 and then add to it based on specific values. In this case, it’s going to be the width of every image in the list.

The problem is, my parameter never, ever changes.

Here is the XSLT I’m using to reset the PARAM:

<xsl:param name="width" select="$width + 36 + (images/item/file/meta/@width * (394 div images/item/file/meta/@height))"/>

Now, I know that the images/item/file/meta/@width * (394 div images/item/file/meta/@height) part works just fine because I’m using it elsewhere and it’s generating a number.

I’ve tried adding that line inside a for-each statement, which didn’t work. I’ve tried adding it inside a template that’s called inside a for-each statement. It didn’t work.

I’m not sure what I’m doing wrong since every resource I can find says I’m doing it right!

Here’s the entire XSLT for the page in question:

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

<xsl:import href="../utilities/master.xsl"/>
<xsl:import href="../utilities/contact-form.xsl"/>

<xsl:param name="width" select="0"/>

<xsl:template match="data">
    <div class="section" id="introduction">
        <div class="header">
            <h1><strong>Guy Haddon-Grant</strong> Artist, Illustrator &amp; Sculptor</h1>           
        </div>
    </div>
    <div class="section" id="information">
        <div class="header">
            <h2>Information About The Artist</h2>
        </div>
        <img id="self-portrait" src="{$workspace}/uploads/{home-page-content/entry/portrait-image/filename}" width="{home-page-content/entry/portrait-image/meta/@width}px" height="{home-page-content/entry/portrait-image/meta/@height}px" alt="A self-portrait of Guy Haddon-Grant" />
        <xsl:apply-templates select="home-page-content/entry/artist-information-text"/>
        <div id="shows-and-exhibitions">
            <h2>Shows and Exhibitions</h2>
            <ul>
                <xsl:for-each select="home-page-content/entry/shows-and-exhibitions/item">
                    <li>
                        <strong id="year"><xsl:value-of select="substring-before(date/date/start, '-')"/></strong> &#8212; <a rel="external" href="{url}" title="View this venue's web site"><strong><xsl:value-of select="title"/>,</strong><xsl:text> </xsl:text><xsl:value-of select="venue"/></a>
                    </li>
                </xsl:for-each>
            </ul>
        </div>
        <div id="awards-and-prizes">
            <h2>Awards and Prizes</h2>
            <ul>
                <xsl:for-each select="home-page-content/entry/awards-and-prizes/item">
                    <li>
                        <strong><xsl:value-of select="substring-before(date/date/start, '-')"/></strong> &#8212; <span><strong><xsl:value-of select="title"/>,</strong><xsl:text> </xsl:text><xsl:value-of select="awarding-body"/></span>
                    </li>
                </xsl:for-each>
            </ul>
        </div>
    </div>
    <div class="section" id="artwork">
        <div class="header">
            <h2>Selected Artwork</h2>
        </div>
        <xsl:for-each select="home-page-artwork/entry">
            <xsl:call-template name="slide-width" />
        </xsl:for-each>
        <p>width is <xsl:value-of select="$width"/></p>
        <ul id="slides" style="width:{$width}px">
            <li class="slide"><xsl:apply-templates select="home-page-content/entry/selected-artwork-text"/></li>
            <xsl:for-each select="home-page-artwork/entry">
                <li class="slide">
                    <img src="{$root}/image/1/0/394/uploads/{images/item/file/filename}" width="{round(images/item/file/meta/@width * (394 div images/item/file/meta/@height))}px" height="394px" alt="{images/item/short-description}" />
                </li>
            </xsl:for-each>
        </ul>
    </div>
    <div class="section" id="contact">
        <div class="header">
            <h2>Contact The Artist</h2>
        </div>
        <xsl:apply-templates select="home-page-content/entry/contact-information-text"/>
        <xsl:call-template name="contact-form"/>
    </div>
</xsl:template>

<!-- Slide Width -->
<xsl:template name="slide-width">
    <xsl:text>*</xsl:text>
    <xsl:param name="width" select="$width + 36 + (images/item/file/meta/@width * (394 div images/item/file/meta/@height))"/>
</xsl:template>

<!-- Artist Information Text -->
<xsl:template match="home-page-content/entry/artist-information-text//*">
    <xsl:element name="{name()}">
        <xsl:apply-templates select="* | @* | text()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="home-page-content/entry/artist-information-text//@*">
    <xsl:attribute name="{name(.)}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

<!-- Selected Artwork Text -->
<xsl:template match="home-page-content/entry/selected-artwork-text//*">
    <xsl:element name="{name()}">
        <xsl:apply-templates select="* | @* | text()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="home-page-content/entry/selected-artwork-text//@*">
    <xsl:attribute name="{name(.)}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

<!-- Contact Information Text -->
<xsl:template match="home-page-content/entry/contact-information-text//*">
    <xsl:element name="{name()}">
        <xsl:apply-templates select="* | @* | text()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="home-page-content/entry/contact-information-text//@*">
    <xsl:attribute name="{name(.)}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

<!-- Headings -->
<xsl:template match="h1 | h2 | h3 | h4" priority="1">
    <xsl:element name="h{substring-after(name(), 'h') + 1}">
        <xsl:apply-templates select="* | @* | text()" />
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

I’m not posting the XML simply because I know my XPATHs are correct. As you can see, I’m using them to get the images and define their width.

What I’m attempting to do is take the resulting number and use it to set the width of a UL via inline styles.

I don’t think Param values can be altered once declared, I’m sure I read this somewhere once, and the resource I just found backs this up (I think, I’m very sleepy and could have misread it).

Variables are set values, global variables can be over-ridden by local ones, params are programmable by the process invoking them, or can have a default value. But, I’m think, they cannot be added to, only over-ridden also.

Just declare a shadow xsl:variable in your main xsl:for-each or xsl:template:

<xsl:param name="width" select="0"/>

<xsl:template match="data">
    <xsl:variable name="actual-width" select="$width + 36 + (images/item/file/meta/@width * (394 div images/item/file/meta/@height))"/>

    <-- Do all your processing, using $actual-width instead of width -->
</xsl:template>

Also, be aware that both xsl:param and xsl:variable elements must be the very first items in your xsl:for-each or xsl:template. They cannot come later in the element.

@designermonkey is correct - xsl:param is a parameter to the current xsl:template (you pass them with xsl:with-param) and xsl:variable is a declared variable within the current scope.

Just remember that XSL is not dynamic like scripting languages and their ilk - variables and parameters are initialised once when transforming, and that’s it.

I think you’re misunderstanding what I’m trying to do, then, I’m probably going about it in the worst way.

Basically, I’m trying to get the width of every image and adding them all together to get one value from which I’m setting the width of the UL element. It won’t be dynamic, I only need to set it once. I’m just trying to avoid having to rely on JS.

The reason I can’t use Actual Width is because it won’t increase the total value as it iterates through the entire list of images. It will just have that one value.

Usually when I run into an issue where the non-dynamic nature of XSLT variables gets in the way, I end up using a recursive named template. This won’t work as is, but might give you an idea for a solution:

<xsl:template name='add-widths'>
<xsl:param name='old-width' />
<xsl:param name='image-entry' />
<xsl:param name='new-width' select='$old-width + $image-entry/images/item/file/meta/@width' />
<xsl:choose>
    <xsl:when test='$image-entry/following-sibling::entry'>
    <xsl:call-template name='add-widths'>
        <xsl:with-param name='old-width' select='$new-width' />
        <xsl:with-param name='image-entry' select='$image-entry/following-sibling::entry' />
    </xsl:call-template>
    <xsl:otherwise>
        <xsl:value-of select='$new-width' />
    </xsl:otherwise>
</xsl:choose>

Yeah, it wasn’t clear that that was what you were trying to do. @ashooner’s solution is pretty much what I would do to recursively pass parameters along.

Thanks for the assist, I ended up just making it so all the images will display with the same width, which actually solved a few other problems down the road.

I might come back to this later but for now I’ve surrendered given that he wants something up by… Oh, in 50 minutes and I still have a contact form to make.

Sorry, double post due to the world’s flakiest internet.

@ashooner’s solution is pretty much what I would do to recursively pass parameters along.

Of course! Never thought about recursion, that solves a problem for me too ;)

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details