Search

I have a page which I only want to show the first few paragraphs until the horizontal rule. After that there will be a ‘read more’-button.

So I have XML like this:

<content>
    <p>My first paragraph</p>
    <p>My second paragraph</p>
    <hr />
    <p>My third paragraph</p>
</content>
<content>
    <p>My first paragraph</p>
    <hr />
    <p>My second paragraph</p>
    <p>My third paragraph</p>
</content>

The output should be something like this:

<p>My first paragraph</p>
<p>My second paragraph</p>
<a href="#">Read more</a>

...

<p>My first paragraph</p>
<a href="#">Read more</a>

My second question offcourse is, when I show the content on a dedicated page, can I filter the hr-tags out if it with XSLT? ;)

Yes, you can do that. Firstly you’ll need the Ninja Technique Template. It enables you to parse your content XML recursively, inserting special rules to fit your need.

Secondly, take a look at preceding-sibling::, it will enable you to “select all nodes that come before hr”.

Thirdly, a single, empty template that matches hr will get rid of it in content view.

You might also introduce your own tag <break /> that separates your content into preview and full article view.

Ok, preceding-sibling seems to do the job, I had however add some more XSLT in case there were no horizontal rules (in that case nothing would get showed). Is this the most effecient way?:

<xsl:choose>
    <xsl:when test="count(content/hr) > 0">
        <xsl:copy-of select="content/p[preceding-sibling::hr]" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:copy-of select="content" />
    </xsl:otherwise>
</xsl:choose>

@phoque:

I use a horizontal rule so my client can easily add a horizontal rule with CKEditor in the backend where he wants to break the article.

I am going to try that empty-template-method you mentioned

Not quite. That way you’re only copying p elements. Replace the third line with

    <xsl:copy-of select="content/*[preceding-sibling::hr]" />

and the sixth line with

    <xsl:copy-of select="content/*" />

Or, as I said, use the Ninja Technique. It’s fun and may come in very handy.

How would you do this then with the Ninja Technique? I looked at the XSLT template, but don’t know yet how to practicly implement it.

Use that stylesheet, add your own template

<xsl:template match="hr" mode="html" />

and replace your instances of copy-of select="content/*" with apply-templates select="content/*" mode="html".

This will, instead of copying the elements, call the template <xsl:template match="*" mode="html" /> to decide what to do. The template itself simply outputs the element and it’s content and, if there are children-elements, call itself again. Basically copying it recursively as copy-of would do. But your custom hr rule will override the default case and, because it’s empty, prevent the Ninjas from returning anything.

A great example is Headline Hierachy. As you can see, it’s Ninja-based as well but catches all headline-elements and does cruel things to them.

Isn’t this method very performance intensive?

I’ve got it working!

I’m a true ninja now… :P

Isn’t this method very performance intensive?

Check your profiler (append ?profile to any of your Symphony-URLs) to see for yourself. :-)

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