Search

Hi there, I’m pretty new to symphony but loving it so far! I’m trying to create a way for users to create unique title tag each page they edit.

I can get this working absolutely fine…. but I want a ‘default’ page title to show if the user doesn’t enter a custom one. I’m calling the template below into the

This is what i have right now - no matter what I do I always get the ‘default’ template (which is $website-name | $page-title) displaying even when the meta-title string is populated.

What i’m trying to do is test to see if the string is NOT empty and then display the custom meta-title. I’ve tried this the other way around (ie testing to see if this is empty) and got the same result.

      <xsl:template name="page-title">
    <xsl:for-each select="data/pages/entry[page=$current-page]">
    <xsl:choose>
      <xsl:when test="string-length(data/pages/entry/meta-title) &gt; 0">
      <xsl:value-of select="meta-title"/>
      </xsl:when>
        <xsl:otherwise>
        <xsl:value-of select="$website-name"/>
    <xsl:text> &#8212; </xsl:text>
    <xsl:value-of select="$page-title"/>
      </xsl:otherwise>
      </xsl:choose>
       </xsl:for-each>
</xsl:template>

Any ideas would be much appreciated. It’s obviously partially working but not returning the right result from the test (which is no doubt due to my noob XSLT skills.

Thanks.

You need to post a sample of your xml.

Hi Tim,

try changing the template to

<xsl:template name="page-title">
    <xsl:for-each select="/data/pages/entry[page=$current-page]">
        <xsl:choose>
            <xsl:when test="meta-title">
                <xsl:value-of select="meta-title"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$website-name"/>
                <xsl:text> &#8212; </text>
                <xsl:value-of select="$page-title"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:template>

I prepended a / to the select of the for-each (just to be sure to start from the root) and changed the condition of your test. In a for-each you are always working in the context of the current element (/data/pages/entry) in this case.

But do you really want to iterate over multiple pages entries and do you have multiple entries? If not just drop the choose

<xsl:template name="page-title">
    <xsl:choose>
        <xsl:when test="/data/pages/entry[page=$current-page]/meta-title">
            <xsl:value-of select="/data/pages/entry[page=$current-page]/meta-title"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$website-name"/>
            <xsl:text> &#8212; </text>
            <xsl:value-of select="$page-title"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Edit: That’s just a guess. If the template doesn’t work we need your XML, like wisolman said.

Hi thanks! Both of those work great… Sorry I didn’t post the xml as I had it working until I added the logic - so was sure my xpath etc was right - just couldn’t get the test to work.

I didn’t realize I could test like that!

So <xsl:when test="meta-title">returns true if there is something stored and false if there isn’t? That is much easier!

Which of the two options you gave is best to use? I will have around 5 pages that use this template so would option 1 or option 2 be best? One is iterating the list while the other is filtering it? Is that right? Which is most efficient?

Thanks again for your help - learning lots.

It can be safer to use string-length() to perform this check. klaftertief’s example above tests for the existence of the element, but not if it has any real contents. In certain situations (say if you’re expecting just a text node inside the element) the test can return a true value even though the element is empty.

This varies from XSLT processor to XSLT processor, so I’ve often used the following so that my code is consistent:

<xsl:if test="string(some/great/element) != ''">
    …
</xsl:if>

This works in both situations (child elements will be transformed to text so that you’re effectively testing for null recursively). XSLT can be a fickle and subtle language sometimes.

To make it a bit more complicated your test can also look like

<xsl:if test="some/great/element != ''">
    …
</xsl:if>

In this case the XSLT processor should do implicit type conversion. It’s a bit shorter, but Tony’s argument for consistence is a valid one.

Regarding your question between the iterating and filtering solution: there will probably only be one entry that fulfills the predicate [page = $current-page] (otherwise you would have multiple meta-title values in your output), so the filtering option is the better one.

Right! Ok I think I get all that. Makes sense where there is only one output I want to use filtering - will change to that to make it cleaner.

Thanks again for all the help and explanation - really helps with getting my head around the best way to do things - and different options! I still don’t totally understand why sometimes i can get an empty element <element></element>verses nothing at all. But hopefully i’ll figure that out as I do more.

Cheers!

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