Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Hamish 96 posts 154 karma points
    Oct 30, 2009 @ 23:00
    Hamish
    1

    How to display only the first paragraph in the bodyText

    I'm trying to list a group of articles and show only the first paragraph in the bodyText? Does anyone know how to do this in XSLT.

    I've tried using umbraco.library:Split to split it out by "<p>" or"&lt;p&gt;" tag but this just seems to break things:

     

    <xsl:variable name="bodyText" select="data[@alias='bodyText']"/>
    <xsl:variable name="bodyTextSplit" select="umbraco.library:Split($bodyText,'&lt;p&gt;')"/>
    <xsl:value-of select="$bodyTextSplit/value[1]"/>

    Any help would be much appreciated... This seems straight forward but i'm getting lost (probably missing something)

     

  • Chris Houston 535 posts 980 karma points MVP admin c-trib
    Nov 02, 2009 @ 19:26
    Chris Houston
    1

    Hi Hamish,

    I saw this post and thought, "oh, I remember how to do that... " well 4 hours later I have the solution for you!

    The test data I used was:

    <p>This is some body text</p>
    <p>This is some more.</p>
    <p>And a whole lot more.</p>

    And the XSLT macro:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [
    <!ENTITY nbsp "&#x00A0;">
    ]>
    <xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:vizioz="urn:vizioz-com:xslt"
    xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
    exclude-result-prefixes="msxml msxsl vizioz umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>

    <xsl:template match="/">

    <!-- Create a node set from your richtext content -->
    <xsl:variable name="bodyText">
    <xsl:text>&lt;set&gt;</xsl:text>
    <xsl:value-of select="$currentPage/data [@alias='bodyText']" disable-output-escaping="yes"/>
    <xsl:text>&lt;/set&gt;</xsl:text>
    </xsl:variable>

    <!-- The above is currently seen as a result tree fragment (RTF) and hence cannot be -->
    <!-- accessed via xpath, so you need to convert it to an XML node -->
    <xsl:variable name="myBodyTextNode" select="vizioz:GetNode($bodyText)"/>

    <!-- And finally to select the first paragraph -->
    <xsl:value-of select="$myBodyTextNode/p[1]"/>

    </xsl:template>

    <msxsl:script language="C#" implements-prefix="vizioz">
    <![CDATA[
    public XmlElement GetNode(string xmlString)
    {
    var xDoc = new XmlDocument();
    xDoc.LoadXml(xmlString);
    return xDoc.DocumentElement;
    }
    ]]>
    </msxsl:script>

    </xsl:stylesheet>

    And the result is:

    This is some body text

    So, what does the above do you might be asking!

    What it does is it takes your richtext bodyText and convert it to an XML node, then returns the first paragraph child node.

    It's a real pain to work out and although there is a "msxsl:node-set" which is meant to convert a string to a node
    set it does not seem to work, the only way seems to be to pass it into a script function as I have done above.

    I hope this is of help :)

    Chris

  • Kurisotofa 27 posts 75 karma points
    Nov 19, 2009 @ 16:53
    Kurisotofa
    0

    A much more elegant solution, as I believe is :

     

    1. Replace '<p>' with '' and '</p>' with '|' (or any other character you prefer, preferably less like to appear in the bodyText)

    <xsl:variable name="list_string" select="umbraco.library:Replace(umbraco.library:Replace(data [@alias = 'bodyText'], '&lt;/p&gt;', '|'), '&lt;p&gt;', '')"/>

     

    2. Split the bodyText into an array, using that particular character as a delimiter

    <xsl:variable name="list_items" select="umbraco.library:Split($list_string, '|')"/>

     

    3. Output the first element of the array

    <xsl:value-of select="$list_items/value [1]"/>

     

  • Kurisotofa 27 posts 75 karma points
    Nov 19, 2009 @ 16:58
    Kurisotofa
    0

    Update :

    Just tried using the paragraph character '§' as the delimiter instead of the vertical lign '|'...

    Works just as well, as is even more unlikely to appear in your bodyText...

     

    Just an idea...

     

    Good luck!

  • Chris Houston 535 posts 980 karma points MVP admin c-trib
    Nov 19, 2009 @ 17:23
    Chris Houston
    0

    Hi,

    I wouldn't use the pipe character as I know a lot of my clients use that, but the § character is very unlikely to be used!

    Obviously both solutions work, no idea which is the optimum solution, I guess it depends if there is a risk of using the delimiter character :)

    Cheers,

    Chris

  • Murray Roke 503 posts 966 karma points c-trib
    Apr 27, 2010 @ 03:41
    Murray Roke
    0

    you could replace \n with space, and then all <\p> with \n

    and use \n delimiter.

Please Sign in or register to post replies

Write your reply to:

Draft