Search

I am trying to add classes to my articles tags. I have change the tags to reflect the nomenclature of discipline. So each project could be tagged Branding, Print, Web. I’d like to assign classes to these tags as they are presented. Thinking I can do this with <xsl:if test="contains(discipline/item, 'Branding')"> Here’s what I have so far.

<p>
  <xsl:text>In this project: </xsl:text>
    <xsl:for-each select="discipline/item">
      <a href="{$root}/discipline/{@handle}"><xsl:value-of select="."/></a>                     
    <xsl:if test="position() != last()">+</xsl:if>
  </xsl:for-each>
</p>

Just not sure when to call the test and how to dynamically add classes to the different disciplines. Do I use <xsl:choose> inside of a <xsl:for-each> statement?

Any help would be grand.

What will the class names be and what element are you trying to add them to?

If I understand correctly what you’re trying to do, my recommendation is to use Allen’s Ninja Technique, but like most things in XSLT, there are many ways to accomplish it.

Maybe you could make use of <xsl:attribute />.

I didn’t know where to insert the test and wasn’t quite sure of the syntax. Should I be using a choose here? but the content to test for would be Branding, Print, or Web and would be assigned classes as follows:

Branding = class=”magenta” Web = class=”cyan” Print = class=”yellow”

Seen in the screenshot:

Attachments:
classes.jpg

So following your code above you’d probably do something like:

<p>
    <xsl:text>In this project: </xsl:text>
    <xsl:for-each select="discipline/item">
        <a href="{$root}/discipline/{@handle}">
                <xsl:choose>
                    <xsl:when test="text() = 'Branding'">
                        <xsl:attribute name="class">magenta</xsl:attribute>
                    </xsl:when>
                    <xsl:when test="text() = 'Web'">
                        <xsl:attribute name="class">cyan</xsl:attribute>
                    </xsl:when>
                    <xsl:when test="text() = 'Print'">
                        <xsl:attribute name="class">yellow</xsl:attribute>
                    </xsl:when>
                </xsl:choose>
            <xsl:value-of select="."/>
        </a>                     
        <xsl:if test="position() != last()">+</xsl:if>
    </xsl:for-each>
</p>

Just one way to do it… and probably not the most efficient and flexible. But it’d work I think.

beautiful. thanks a ton for the help!

I would’ve taken another approach, why use colors as class names when you have a semantic meaningful element name content:

<ul>
  <xsl:text>In this project: </xsl:text>
  <xsl:apply-templates select="discipline/item" mode="discipline-link"/>
</ul>

<xsl:template match="discipline/item" mode="discipline-link">
  <li class="{text()}">
    <a href="{$root}/discipline/{@handle}">
      <xsl:apply-templates/>
    </a>
  </li>
</xsl:template>

With this approach you could easily extend the number of disciplines without changing the code. The ‘+’ could just as well be added with some CSS since it’s more of a styling imo.

And yes, I changed it to an unordered list, felt like one… code isn’t tested btw.

a slightly different approach to craig’s:

    <a href="{$root}/discipline/{@handle}">
            <xsl:attribute name="class">
                <xsl:choose>
                    <xsl:when test="text() = 'Branding'"><xsl:value-of select="'magenta'" /></xsl:when>
                    <xsl:when test="text() = 'Web'"><xsl:value-of select="'cyan'" /></xsl:when>
                    <xsl:when test="text() = 'Print'"><xsl:value-of select="'yellow'" /></xsl:when>
                </xsl:choose>
            </xsl:attribute>
        <xsl:value-of select="."/>
    </a>   

but there probably should be a xsl:otherwise statement for a default value.

Alright just when I thought I had this thing whipped.

For some reason its not working when I try to apply to style inside of an h2 tag. Maybe I’m just missing something. I can get the text to appear but the class is blank. Help?

<xsl:template match="data">
  <div class="grid_20">
    <div class="post">
      <div class="post-content">    
      <!--Fixthis-->            
      <h2>
        <xsl:attribute name="class">
          <xsl:choose>
            <xsl:when test="text() = 'Branding'"><xsl:value-of select="'magenta'" /></xsl:when>
            <xsl:when test="text() = 'Web'"><xsl:value-of select="'cyan'" /></xsl:when>
            <xsl:when test="text() = 'Print'"><xsl:value-of select="'yellow'" /></xsl:when>
            <xsl:otherwise><xsl:value-of select="white"/></xsl:otherwise>
          </xsl:choose>
        </xsl:attribute>
        <xsl:value-of select="discipline//item[@handle = $tag]"/>
      </h2><!--endfixthis-->

      <h3 class="script">A few samples from the <span><xsl:value-of select="discipline//item[@handle = $tag]"/></span> discipline.</h3>

      <xsl:apply-templates select="discipline/entry[position() &lt; 6]" mode="short"/>        

      </div>
    </div>
  </div>

  <div id="sidebar" class="grid_4">
    <xsl:call-template name="recent-projects"/>
  </div>
</xsl:template>

Which is outputting this:

<div class="post-content">
  <h2 class="">Branding</h2>
  <h3 class="script">A few samples from the <span>Branding</span> discipline.</h3>
  <div class="project grid_4 alpha">...

Your “when” conditions do not match any nodes, so you end up outputting “otherwise” – but there you are missing the single quotes around the string ‘white’. I should be:

<xsl:otherwise><xsl:value-of select="'white'"/></xsl:otherwise>

how do I get it to match the discipline/item node? <xsl:apply-templates select="discipline/item" /> ? Sorry still learing XSLT. Got the single quotes. Now its actually out outputting white. Thanks.

Might be nice to know that you don’t specifically need <xsl:value-of /> in that case, you can simply just put it as <xsl:otherwise>white</xsl:otherwise>

I do agree with pertoyra though that use semantic class names would be better. What happens if 6 months down the track ‘white’ needs to be ‘pink’? Instead of just updating the CSS, you’ll need to update the XSLT again, or worse, ‘white’ will be the class name, but the class will do something ‘pink’ about it which can make maintenance a bit confusing :)

In terms of matching, it depends on your XML. At the moment text() is referring to data which I don’t think is correct. Do you have a datasource that is outputting this information, much like your original post?

how do I get it to match the discipline/item node?

Without seeing the XML I can just guess it should be s.th. like:

      <xsl:choose>
        <xsl:when test="discipline//item/text() = 'Branding'"><xsl:value-of select="'magenta'" /></xsl:when>
        <xsl:when test="discipline//item/text() = 'Web'"><xsl:value-of select="'cyan'" /></xsl:when>
        <xsl:when test="discipline//item/text() = 'Print'"><xsl:value-of select="'yellow'" /></xsl:when>
        <xsl:otherwise><xsl:value-of select="white"/></xsl:otherwise>
      </xsl:choose>

There might be a more elegant solution for what you try to achieve by applying an additional template to your discipline node. apply-templates is my favorite in XSLT…

test="discipline//item/text()

is exactly what I was looking for. I just couldn’t figure out where to call that. Thanks michael-e.

Glad you got it working!

never mind. that didn’t work. Here is my XML: Pastie

I basically just want to test what the h2 value is. Right now it comes back as either Print, Branding, or Web. They are basically tags that I tag my projects by. <xsl:value-of select="discipline//item[@handle = $tag]"/> is getting the text that I need. Just not sure how to test for it.

P.S. Anyone know how to copy the XML from the debug screen without grabbing all the line numbers? Is there another spot to view the XML?

Thanks again everyone!!

Figured it out.

<h2>
  <xsl:attribute name="class">
    <xsl:choose>
      <xsl:when test="discipline//item[@handle = $tag] = 'Branding'"><xsl:value-of select="'magenta'" /></xsl:when>
      <xsl:when test="discipline//item[@handle = $tag] = 'Web'"><xsl:value-of select="'cyan'" /></xsl:when>
      <xsl:when test="discipline//item[@handle = $tag] = 'Print'"><xsl:value-of select="'yellow'" /></xsl:when>
      <xsl:otherwise>white</xsl:otherwise>
     </xsl:choose>
    </xsl:attribute>
    <xsl:value-of select="discipline//item[@handle = $tag]"/>
 </h2>

@dallas - have you ever thought about adding a field to each discipline that someone can set to a certain color or value in the admin? that way you just need to include that value in your xml output and not worry about a xsl:choose statement. this will also allow you to not worry about adding additional checks if you decide to expand your disciplines to more than what you have right now.

i’m not sure how your site structure is, but just a thought

Hey guys, just a quick (lil’ off topic) question…

I have a field called “Site” on my section. And I want only to show a link called “Visit the site” when there field is filled. When the user leave it blank, show nothing. I tried some things but I didn’t find a cool overview of the “test” attribute of XSL.

First thing that comes to my mind:

<xsl:if test="site">
    <a href="{site}">Visit the site</a>
</xsl:if>

or (and this is the perfect opportunity to dip into the apply-template awesomeness)…

<xsl:apply-templates select="site" />

and

<xsl:template match="site">
    <a href="{site}">Visit the site</a>
</xsl:template>

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