3 users online. Create an account or sign in to join them.Users
XSLT Ninjas: Splitting a string and wrap its parts in spans
This is an open discussion with 16 replies, filed under General.
Search
How are you deciding how many words per span? Are there always three spans?
Sometimes you should just ask the girl sitting on the other side of the desk before posting on the forum. This is how it works:
<xsl:template name="substring">
<xsl:param name="text" />
<xsl:call-template name="row">
<xsl:with-param name="text" select="$text" />
</xsl:call-template>
</xsl:template>
<xsl:template name="row">
<xsl:param name="text" />
<xsl:param name="storage" />
<xsl:param name="count" select="0" />
<xsl:param name="total" select="70" />
<xsl:choose>
<xsl:when test="$count < $total and $text != ''">
<xsl:variable name="word" select="substring-before($text, ' ')" />
<xsl:call-template name="row">
<xsl:with-param name="text" select="substring-after($text, ' ')" />
<xsl:with-param name="storage" select="concat($storage, ' ', $word)" />
<xsl:with-param name="count" select="$count + string-length($word)" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<span><xsl:value-of select="$storage" /></span>
<xsl:if test="$text != ''">
<xsl:call-template name="substring">
<xsl:with-param name="text" select="substring-after($text, ' ')" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
:)
Don’t be so modest. It’s not like I scribbled this down in a flash of ingenuity. But hey, sometimes the question if one could use a variable does the trick, eh.
:)
I was going to try and approach it without any recursion, so wanted to know quite how to were splitting into three spans without having to dissect your recursion logic first…
The initial string should be split by length: the limit is currently set to 70 letters (which means that my string is much longer than in my example of course). The first whitespace after passing the 70 letter limit will be used as splitting point.
If you have an idea for an approach without recursion I’d be interested.
Aha! That makes more sense. I was struggling to figure out how your example above made three spans with such a short initial string :-P
How about this: http://gist.github.com/346948
Actually that won’t work. I’m splitting with words, so I completely ignored your requirement for splitting on letters, and allowing for flexible boundaries. Recursive might be the way to go then :-/
Well, that looks cool though.
The text I’m trying to split is an excerpt of an article that is shown in a column. I used letters for splitting as words can be very long in German.
Do you know if it should be considered as best practice to use the EXSLT library (thinking of speed etc.)?
I just refined my template and added a prefix and a suffix which can be added to the first or the last span respectively:
<xsl:template name="substring">
<xsl:param name="text" />
<xsl:param name="prefix" />
<xsl:param name="suffix" />
<xsl:call-template name="row">
<xsl:with-param name="prefix" select="$prefix" />
<xsl:with-param name="suffix" select="$suffix" />
<xsl:with-param name="text" select="$text" />
<xsl:with-param name="count" select="string-length($prefix)" />
</xsl:call-template>
</xsl:template>
<xsl:template name="row">
<xsl:param name="text" />
<xsl:param name="prefix" />
<xsl:param name="suffix" />
<xsl:param name="storage" />
<xsl:param name="count" select="0" />
<xsl:param name="total" select="70" />
<xsl:choose>
<xsl:when test="$count < $total and $text != ''">
<xsl:variable name="word">
<xsl:choose>
<xsl:when test="contains($text, ' ')">
<xsl:value-of select="substring-before($text, ' ')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="row">
<xsl:with-param name="text" select="substring-after($text, ' ')" />
<xsl:with-param name="prefix" select="$prefix" />
<xsl:with-param name="suffix" select="$suffix" />
<xsl:with-param name="storage" select="concat($storage, ' ', $word)" />
<xsl:with-param name="count" select="$count + string-length($word)" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<span>
<xsl:copy-of select="$prefix" />
<xsl:value-of select="$storage" />
<xsl:if test="$text = ''">
<xsl:copy-of select="$suffix" />
</xsl:if>
</span>
<xsl:if test="$text != ''">
<xsl:call-template name="substring">
<xsl:with-param name="text" select="$text" />
<xsl:with-param name="suffix" select="$suffix" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I needed this snipped to create this layout which can’t be achieved using plain CSS and needs this extra markup:
Although it’s dummy text it looks like there is one word missing at the end of each line.
Nah, it just looks like there’s a extra bit of padding.
Also, isn’t that German? Certainly isn’t Lorem Ipsum.
Although it’s dummy text it looks like there is one word missing at the end of each line.
Michael, you’re right. Haven’t noticed that yesterday. It’s fixed in the template now.
Nah, it just looks like there’s a extra bit of padding.
That “extra bit” padding and margin can get quite tricky depending on the page context and the browsers you have to support.
Also, isn’t that German? Certainly isn’t Lorem Ipsum.
No, it’s not lorem ipsum — it’s the way we talk :o)
@dougoftheabaci: It’s “Pseudo-German” dummy-text, making no real sense.
@Nils:
it’s the way we talk
I am looking forward to hearing you talk like this — see you in London!
Michael, meine Sätze fangen immer an mit: “Es war einmal …” ;)
(Sorry for the German, nothing that really makes sense …)
Create an account or sign in to comment.
I have an element
that I want to separate into multiple substrings and wrap these in
spanelements. Like this:<p> <span>This is my string</span> <span>stored somewhere</span> <span>in my XML.</span> </p>This is what I’ve done so far
<xsl:template name="substring"> <xsl:param name="text" /> <span> <xsl:call-template name="row"> <xsl:with-param name="text" select="$text" /> </xsl:call-template> </span> </xsl:template> <xsl:template name="row"> <xsl:param name="text" /> <xsl:param name="count" select="0" /> <xsl:param name="total" select="70" /> <xsl:choose> <xsl:when test="$count < $total and $text != ''"> <xsl:variable name="word" select="substring-before($text, ' ')" /> <xsl:value-of select="$word" /> <xsl:text> </xsl:text> <xsl:call-template name="row"> <xsl:with-param name="text" select="substring-after($text, ' ')" /> <xsl:with-param name="count" select="$count + string-length($word)" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:if test="$text != ''"> <xsl:call-template name="substring"> <xsl:with-param name="text" select="substring-after($text, ' ')" /> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template>but this will (of course) result in the following markup:
<p> <span> This is my string <span> stored somewhere <span>in my XML.</span> </span> </span> </p>Is there an XSLT Ninja around that has an idea how to generate my desired markup?