tags:

views:

268

answers:

3

I am trying to emulate StringBuilder behavior in an XSL. Is there a way to do this. It seems pretty hard given the fact that XSLT is a functional programming language

+2  A: 

Have a look at the concat() and string-join() functions, maybe that's what you are after.

Tomalak
I am looking for just the appending functionality. And that means I want to store the result after appending in the same variable
Varun Mahajan
No, this won't be possible. Variables are immutable in XSLT, you cannot change them. You can maybe use recursion to get a similar result. What exactly do you want to do? Can you post some code to your question?
Tomalak
I think recursion can work here.Thanks everybody.
Varun Mahajan
+1  A: 

You can use all available standard XPath 2.0 string functions, such as concat(), substring(), substring-before(), substring-after(), string-join(), ..., etc.

However, in case you need a very fast implementation of strings (even faster than the .NET string class) you'll probably be interested in the C# implementation of the finger-tree data structure and the extension functions I provided for the Saxon XSLT processor that wrap the finger-tree-based string.

Dimitre Novatchev
+1  A: 

You can get the accumulting concats quite simply with just a little bit of recursion if you're looking at a node-set (so long as you can construct the xpath to find the node-set), doing this so you can add arbitrary bits and pieces in and out of the flow it starts getting messy.

Try this for starters (does join as well):

<xsl:template match="/">
     <xsl:variable name="s">
        <xsl:call-template name="stringbuilder">
         <xsl:with-param name="data" select="*" /><!-- your path here -->
        </xsl:call-template>
     </xsl:variable>
     <xsl:value-of select="$s" /><!-- now contains a big concat string -->
</xsl:template>

<xsl:template name="stringbuilder">
    <xsl:param name="data"/>
    <xsl:param name="join" select="''"/>
    <xsl:for-each select="$data/*">
     <xsl:choose>
      <xsl:when test="not(position()=1)">
       <xsl:value-of select="concat($join,child::text())"/>
      </xsl:when>
      <xsl:otherwise>
       <xsl:value-of select="child::text()"/>
      </xsl:otherwise>
     </xsl:choose>  
    </xsl:for-each>
</xsl:template>

All manner of extensions to that may be required: perhaps you want to trim, perhaps you want to tunnel through hierarchies as well. I'm not sure a bulletproof general solution exists.

annakata
The $join variable does not serve any purpose. It is confusing and misleading! Instead of "concat($join,child::text())" use just "text()". The whole <xsl:for-each> is unnecessary. use a single: "xsl:copy-of select='$data/text()'"
Dimitre Novatchev
You really are a special kind of troll aren't you Dimitre? VERY VERY CLEARLY the join parameter is optional (see where it has a select?) which allows the builder to function as a .join method (see where I say "does join as well"?) which requires the loop, which provides expansion ("for starters"?).
annakata
@annakata I completely don't understand what is "VERY VERY CLEARLY" to you. I feel very curious as to what this may be. Can you explain and provide a little example of the use of the "join" parameter?
Dimitre Novatchev
Sure. If I was to include <xsl:with-param name="join" select="'TROLL'"/> on a set of text a,b,c,d it would product the result "aTROLLbTROLLcTROLLd"
annakata
Now I see what you meant. Is indeed a downvote and several signals that this was not understandable, necessary to make you finally explain what you meant? Your answer will benefit greatly if you explain *in it* the intended use of the "join" parameter. Not much to do with the original append f-ty q.
Dimitre Novatchev
You're happy to explain *finger-trees* with a handy *white-paper* but string joining baffles you? Do I *really* need to explain how "join" relates to "string"? If you know XSLT as you claim how is it you don't understand optional params? My answer would benefit from you not being here.
annakata
Actually whatever, I'm done with this pointless merry-go-round. Downvote away, I'm not feeding you any more.
annakata
Thanks @annakata. And @annakata and @Dimitre, cool down a bit. Thanks to you both
Varun Mahajan
"string-join" and "join" are very different things. An answer will benefit Greatly if more attention is paid on explaining and being precise vs sloppy. If one really wants to provide an useful answer, dropping just a line without an example isn't that at all. I think you may do better.
Dimitre Novatchev