phpxmlxsltsymphony-cms

Maximum length XSLT but keep full paragraphs in output


I'm working with symphony for a few weeks now and getting the hang of it, really loving all the base functionality.

I have a question since I'm not quite sure how to solve this: I have a news/blog page for the project I'm working on. Sometimes the articles are short sometimes very long. What I would like to do, is display an amount of paragraphs but stop when an x amount of characters are found. I Found methods to count the string length, but I would like it to work like this.

<p>paragraph with 20 chars</p>
<p>paragraph with 300 chars</p>
<p>paragraph with 500 chars</p> 

etc.

Now I would like to configure a max of lets say, 200 chars. the second paragraph will exceed the amount, but I want the content to be displayed both the first and second paragraph. so it will actually be 320 characters (excluding the html and whitespaces).

I hope I'm not to vague, and someone knows where I should go with this. The best option would be to edit the data source I guess, but it doesn't seem like a clean method to me allthough it should reduce the load slightly.

Anyone care to point me in the right direction?


Solution

  • If I read the question correctly, you want to output minimum paragraphs so that the total character count of the characters in the paragraphs is greater than the desired number of characters.

    For example, if you have a paragraphs of 20, 30 and 40 characters. With a stop of 19, you'd only spit out the first, with a stop of 21 you'd output paragraphs 1 and 2 (21<20+30) and with any stop number greater than 50 you'd output all three.

    If that is correct, the below output will do what you need - if you change this line:

    <xsl:if test="30 &gt; string-length($prev)">
    

    Where 30 becomes the desired length of string to stop at.

    This XSLT template ...

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:template match="/">
            <xsl:apply-templates/>
        </xsl:template>
        <xsl:template match="ps">
            <h2>
                <xsl:value-of select="./@name"/>
            </h2>
            <xsl:apply-templates/>
        </xsl:template>
        <xsl:template match="p">
            <xsl:variable name="prev">
                <xsl:for-each select="preceding-sibling::node()">
                    <xsl:value-of select="."/>
                </xsl:for-each>
            </xsl:variable>
            <xsl:if test="30 &gt; string-length($prev)">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>
    

    ... When applied to this document ...

    <pss>
        <ps name="test1">
            <p>paragraph with 20 chars</p>
            <p>paragraph with 300 chars</p>
            <p>paragraph with 500 chars</p>
        </ps>
        <ps name="test2">
            <p>paragraph with 20 chars much greater characters</p>
            <p>paragraph with 300 chars</p>
            <p>paragraph with 500 chars</p>
        </ps>
        <ps name="test2">
            <p>few chars</p>
            <p>few chars</p>
            <p>few chars</p>
        </ps>
    </pss>
    

    ... Produces this output.

    <h2>test1</h2>
    <div>
        <p>paragraph with 20 chars</p>
        <p>paragraph with 300 chars</p>
    </div>
    <h2>test2</h2>
    <div>
        <p>paragraph with 20 chars much greater characters</p>
    </div>
    <h2>test2</h2>
    <div>
        <p>few chars</p>
        <p>few chars</p>
        <p>few chars</p>
    </div>