Search

What I want to do, is if the current path is "/a/b/c/d/" I want to create a string a a_b a_b_c a_b_c_d to use as a body class.

I'm very new to XSLT... trying to learn it, but hitting a brick wall with this foreach statement. I'm using the String Utility functions from here: http://getsymphony.com/download/xslt-utilities/view/54569/

Could someone please tell me why this for-each does nothing?

<xsl:template name="page-class">
<xsl:param name="paths" select="string:split($current-path,'/')" />
<xsl:for-each select="$paths">
<xsl:value-of select="'asdf'" />
</xsl:for-each>
</xsl:template>

I think if I could just get this for-each working I can do the rest. Thanks in advance for any help

Sorry, current path of "/a/b/c/d" should create a string: a a_b a_b_c a_b_c_d

Ugh, formatting keeps removing the underscores. "a a(underscore)b a(underscore)b(underscore)c"

Markdown messed up the result you want to get, please wrap it as code so we can understand :)

EDIT you're too fast :D

<div class="{translate($current-path,'/','_')}" />

or if you need more fancy stuff in your class attribute:

<xsl:attribute name="class">
    <xsl:value-of select="translate($current-path,'/','_')" />
    more fancy stuff...
</xsl:attribute>

Thanks.. but that isn't quite what I need.

I need for the URL "/cars/honda/2006/" to create three classes, so the string looks like this:

cars cars_honda cars_honda_2006

I think I can handle that part on my own if I could just get that for-each working.

Turns out to be harder than I thought, but here's a possible solution:

<xsl:template match="/">
    <xsl:variable name="tokens" select="str:split('ab/cde/fg', '/')"></xsl:variable>

    <xsl:call-template name="recursive">
        <xsl:with-param name="tokens" select="$tokens" />
    </xsl:call-template>
</xsl:template>


<xsl:template name="recursive">
    <xsl:param name="tokens" />
    <xsl:param name="index" select="1" />

    <xsl:if test="$index &lt;= count($tokens)">
        <xsl:for-each select="$tokens">
            <xsl:if test="position() &lt;= $index">
                <xsl:value-of select="." />

                <xsl:if test="position() != $index">
                    <xsl:text>_</xsl:text>
                </xsl:if>
            </xsl:if>
        </xsl:for-each>

        <xsl:text> </xsl:text>

        <xsl:call-template name="recursive">
            <xsl:with-param name="tokens" select="$tokens" />
            <xsl:with-param name="index" select="$index +1" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>

Thank you... that is extremely helpful!

It looks like just what I need, but I still don't think that for-each is working.

Here's my test code:

<xsl:template name="page-class">
    <xsl:variable name="tokens" select="string:split('ab/cde/fg', '/')"></xsl:variable>

    <xsl:value-of select="'!'" />
    <xsl:for-each select="$tokens">
            <xsl:value-of select="'test'" />
    </xsl:for-each>
    <xsl:value-of select="'?'" />

</xsl:template>

This is what I would expect the output to be: !testtesttest?

The actual output is: !?

Weird... your code works for me.

Looks like this is the problem, then?

XSL enabled
libxslt Version 1.1.17
libxslt compiled against libxml Version 2.6.26
EXSLT   enabled
libexslt Version    1.1.17

Thanks for your help =)

Would you mind pasting your entire template? Thanks :)

base.xsl

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

<xsl:import href="string-utils.xsl"/>
<!--<xsl:import href="functions/page-title.xsl"/>-->
<xsl:import href="page-class.xsl"/>
<!--<xsl:import href="blocks/navigation.xsl"/>-->
<!--<xsl:import href="blocks/scripts.xsl"/>-->

<xsl:output method="xml"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
    omit-xml-declaration="yes"
    encoding="UTF-8"
    indent="yes"/>

<xsl:template match="/">
<html lang="en" class="no-js">
    <head>
        <title><!--<xsl:call-template name="page-title"/>--></title>
        <meta name="description" content=""/>       
        <link rel="stylesheet" href="{$workspace}/assets/css/normalize.css"/>
        <link rel="stylesheet" href="{$workspace}/assets/css/grid.css"/>
        <link rel="stylesheet" href="{$workspace}/assets/css/template.css"/>
        <link rel="stylesheet" href="{$workspace}/assets/css/assets.css"/>
        <link rel="stylesheet" href="{$workspace}/assets/css/main.css"/>    
        <!--<xsl:call-template name="scripts"/>-->
    </head>
    <body class="{$current-page} container">
        <header>
            <h1><a href="{$root}"><xsl:value-of select="$website-name"/></a></h1>
            <xsl:call-template name="page-class"/>
            <!--<xsl:apply-templates select="data/navigation"/>-->
        </header>
        <div id="main">
            <xsl:apply-templates/>
        </div>
        <footer>&#169; <xsl:value-of select="$this-year"/>&#160;<xsl:value-of select="$website-name"/></footer>     
    </body>
</html>
</xsl:template>

</xsl:stylesheet>

page-class.xsl

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

<xsl:import href="string-utils.xsl"/>

<xsl:template name="page-class">
    <xsl:variable name="tokens" select="string:split('ab/cde/fg', '/')"></xsl:variable>

    <xsl:value-of select="'!'" />
    <xsl:for-each select="$tokens">
            <xsl:value-of select="'test'" />
    </xsl:for-each>
    <xsl:value-of select="'?'" />

</xsl:template>


</xsl:stylesheet>

Oh, I overlooked your first post. What I am using is the exslt split function which differs in implementation from the split function in the utility. Haven't dug into the utility very much, but I think you're better off using the exslt function because it returns a node-set so you can do that fancy for-each.

Everything you need is declaring the correct namespace in the xsl:stylesheet declaration (here's an howto) and of course removing the utility which would cause namespace issues (or something like that).

Hope this makes sense to you, even if you're just beginning :)
Just to make sure, you don't need to download anything to use exslt functions because they're shipped with most xslt compilers (yours too, as you can see from the phpinfo above).

Excellent, thanks so much! :)

And it works gloriously. Thanks again!!

Awesome!

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