2

I need to split a comma delimited string with xslt 1.0 on the client side .... Is such a thing possible??

I tried a method like

Stackoverflow Solution

I got an error on firefox saying it detected recursion and it halts there. My problem is I am returning data from my SQL server as XML and there is a 1 to many relationship, 1 blogpost record with multiple "tags" [ie #cars]. So I add the "tags" as a comma delimited field inside of an xml tag and I want to split it again on the client side. Alternatively if there is some way to simply create a nested field list from the SQL Server XML that would work too

ie instead of "cars, red, 2010" I could return

<tags>
    <tag>cars</tag>
    <tag>red</tag>
    <tag>2010</tag>
</tags>

I am using MS SQL Server 2008, ASP.NET 4.0 and XSLT 1.0 on the browser so those are the tools available to me. Thanks in advance!

Community
  • 1
  • 1
Jordan
  • 2,708
  • 4
  • 22
  • 35
  • 1
    Parsing strings with XSLT 1.0 and then manipulating the results as nodes requires [EXSLT](http://exslt.org). **Avoid** stretching the limits of client-side XSLT. Instead, use the power of MSSQL to craft the XML the way it's easy for the client to process it. It is certainly possible, but you're not giving any indication of what your tables and data look like, so no suggestion here, just the hint that this is the way to go. – Lumi Jun 21 '11 at 06:06
  • 1
    If you're determined to split the delimited string on the client side, you might try javascript instead of XSLT: http://www.exslt.org/str/functions/tokenize/str.tokenize.js – LarsH Jun 21 '11 at 06:32
  • 1
    Do not perform transformations using the browser built-in processor. – Emiliano Poggi Jun 21 '11 at 09:13
  • Good question, +1. See my answer for a complete and generic XSLT 1.0 solution. – Dimitre Novatchev Jun 21 '11 at 13:12

2 Answers2

3

People are right that the XML can be generated at the server side, however if you are determined to delay this generation, here is how to do this on the client using XSLT1.0 (XSLT 2.0 can just use the XPath 2.0 standard function tokenize(), but XSLT 2.0 is not directly supported by today's browsers):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  <tags>
   <xsl:apply-templates/>
  </tags>
 </xsl:template>

 <xsl:template match="text()" name="split">
   <xsl:param name="pText" select="."/>
   <xsl:param name="pDelim" select="', '"/>
   <xsl:param name="pTagName" select="'tag'"/>

     <xsl:if test="string-length($pText) >0">
       <xsl:element name="{$pTagName}">
         <xsl:value-of select=
         "substring-before(concat($pText, $pDelim), $pDelim)"/>
       </xsl:element>

       <xsl:call-template name="split">
        <xsl:with-param name="pText" select=
         "substring-after($pText, $pDelim)"/>
        <xsl:with-param name="pDelim" select="$pDelim"/>
        <xsl:with-param name="pTagName" select="$pTagName"/>
       </xsl:call-template>
     </xsl:if>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document (your provided string wrapped in a top element to make it a well-formed XML document, so that this can be processed with XSLT):

<t>cars, red, 2010</t>

the wanted, correct result is produced:

<tags>
   <tag>cars</tag>
   <tag>red</tag>
   <tag>2010</tag>
</tags>

Do note: the genericity of this solution -- the text, the delimiting string and the "tagname" are all specified as parameters.

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
0

If you instead kept your data as XML (ie. not splitting the HTML down to a comma-separated list), you may be able to use the data directly.

declare @data as XML

set @data = '<tags>'
          + '<tag>cars</tag>'
          + '<tag>red</tag>'
          + '<tag>2010</tag>'
          + '</tags>'

SELECT tag.value('text()[1]', 'varchar(50)') as 'tags'
FROM   @data.nodes('/tags/tag') AS tags(tag)
Black Light
  • 2,358
  • 5
  • 27
  • 49