0

How to change the delimiter from semicolon to comma and sort the values in alphabetical order in XSLT? Please advise.

Existing tags

<component>
    <rate>T;P;C;X;R</rate>
</component>

Expected tags

<component>
    <rate>C,P,R,T,X</rate>
</component>
DJay E
  • 15
  • 1
  • 7

2 Answers2

2

The part with changing the delimiter is easy:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/component">
    <component>
      <rate>
        <xsl:value-of select="translate(rate, ';', ',')"/>
      </rate>
    </component>
  </xsl:template>
</xsl:stylesheet>

But, for the sorting part, it's a bit more challenging...

Babelabout
  • 445
  • 3
  • 15
0

If you can use XSLT 3.0, you can use tokenize(), string-join(), and sort()...

<xsl:template match="rate">
  <xsl:copy>
    <xsl:value-of select="string-join(sort(tokenize(normalize-space(),';')),',')"/>
  </xsl:copy>
</xsl:template>

If you can use XSLT 2.0, you can use tokenize() and string-join(), but you'll have to use xsl:sort (or xsl:perform-sort) to do the sorting...

<xsl:template match="rate">
  <xsl:variable name="rates" as="item()*">
    <xsl:for-each select="tokenize(normalize-space(),';')">
      <xsl:sort data-type="text"/>
      <xsl:value-of select="."/>
    </xsl:for-each>
  </xsl:variable>
  <xsl:copy>
    <xsl:value-of select="string-join($rates,',')"/>
  </xsl:copy>
</xsl:template>
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
  • Thanks @Daniel, Babelabout .. This helps. Unfortunately, we are on XSLT 1.0 and so can you pls advise how to get this done on sorting? – DJay E Jun 20 '17 at 03:35
  • @DJayE Which XSLT 1.0 processor are you using? – michael.hor257k Jun 20 '17 at 04:12
  • @michael.hor257k A legacy server processes XSLT and transforms into a XML file for other systems. So had to live with XSLT 1.0 – DJay E Jun 20 '17 at 15:00
  • @DJayE - Do you know what XSLT processor your legacy server uses? I think Michael is asking so we know what extension functions might be supported. – Daniel Haley Jun 20 '17 at 15:08
  • 1
    @DJayE Daniel Haley is correct. If you don't know which processor it is, find out: https://stackoverflow.com/questions/25244370/how-can-i-check-which-xslt-processor-is-being-used-in-solr/25245033#25245033 – michael.hor257k Jun 20 '17 at 16:54
  • Just got to know that it allows 2.0 and so as suggested, I can try using tokenize and string-join .. – DJay E Jun 20 '17 at 17:01
  • @DanielHaley What is "item()*" in the code snippet that you've shared? – DJay E Jun 20 '17 at 17:05
  • @DJayE - That specifies that the variable `rates` is a sequence of zero or more items (nodes or atomic values). – Daniel Haley Jun 20 '17 at 17:14
  • Understood, Thanks @DanielHaley – DJay E Jun 20 '17 at 17:42
  • @DanielHaley If I already have the "rate" tag in a variable say ''xyz", how to pass this "$xyz" into the code snippet of XSLT 2.0 that you've shared. Please help. – DJay E Jun 20 '17 at 20:24
  • @DJayE - You could add a mode to the template from my answer (like ``) and then apply-templates to the `$xyz` variable (like: ``). – Daniel Haley Jun 20 '17 at 20:34
  • Some change happened with the requirement. There are individual tags and the input seems now like the below - `code` X T C P `code` Expected output is `code' C,E,P,T,X `code` Please help on this. – DJay E Jun 25 '17 at 22:02