tags:

views:

64

answers:

4

I have an XML file:

<schools>
    <schcool>
     school1, school2, school3, school4, school5
     </schcool>
    </schools>

I want to write XSLT (version 1.0) to change the result to a reverse order like this:

   <schools>
    <schcool>
     school5, school4, school3, school2, school1
     </schcool>
    </schools>

Can anyone help me? Many thanks.

DY

+4  A: 
<template name="split" xmlns="http://www.w3.org/1999/XSL/Transform"&gt;
  <param name="s" />
  <param name="withcomma" select="false()" />
  <choose>
    <when test="contains($s, ',')">
      <!-- if there is still a comma, call me again
           with everything after the first comma... -->
      <call-template name="split">
        <with-param name="s" select="substring-after($s, ',')" />
        <with-param name="withcomma" select="true()" />
      </call-template>
      <!-- ...and print afterwards the current part -->
      <value-of select="substring-before($s, ',')" />
      <if test="$withcomma">
        <text>, </text>
      </if>
    </when>
    <otherwise>
      <!-- No comma left in the remaining part: print the rest -->
      <value-of select="$s" />
      <if test="$withcomma">
        <text>, </text>
      </if>
    </otherwise>
  </choose>
</template>

You might have to fiddle a bit with the whitespace (look up the XPath function 'normalize-space()') to get the exact result, but the reverse sorting in principle is shown in the code above. Call it from your other templates like this:

  <call-template name="split">
    <with-param name="s" select="." />
  </call-template>
Boldewyn
Thank you very much.
Daoming Yang
De nada. Actually, recursive calls to templates are quite frequent in XSLT. You should get used to this technique.
Boldewyn
Beware, your function will return nothing if there aren't any commas in the text...
Erlock
...hmm. Why? The case without commata is handled by the otherwise clause, as far as I can see. It even shouldn't rpint out a superfluous trailing comma.
Boldewyn
OK, you were half-right. There **WAS A BUG** in the old version, I just corrected it the other minute.
Boldewyn
...I hate the value="" and select="" attributes. I always mix them up.
Boldewyn
Tested in Xalan: Without comma (value was "school1") the output is, as expected, precisely "school1".
Boldewyn
I did a test, it about output the original text.
Daoming Yang
@Boldewyn, (+1) Thanks a lot. I just copied your code, splitted the string text using \r and printed each segement in new line.
sangam
+1  A: 

A variant without xsl:choose:

  <xsl:template name="reverse">
    <xsl:param name="text"/>
    <xsl:param name="comma" select="false()"/>
    <xsl:variable name="item" select="substring-before(concat($text, ','), ',')"/>    
    <xsl:if test="normalize-space($item) != ''">
      <xsl:call-template name="reverse">
        <xsl:with-param name="text" select="substring-after(concat($text, ','), concat($item, ','))"/>
        <xsl:with-param name="comma" select="true()"/>
      </xsl:call-template>
    </xsl:if>
    <xsl:value-of select="$item"/>
    <xsl:if test="$comma and $item != ''">
      <xsl:text>,</xsl:text>
    </xsl:if>
  </xsl:template>
Erlock
Hi Erlock, Thank you as well.
Daoming Yang
A: 

Hi Boldewyn,

Thank you. You have save my time.

I remove the space by this:

<xsl:call-template name="split">
     <xsl:with-param name="s" select="normalize-space(.)" />
</xsl:call-template>

Many thanks.

DY

Daoming Yang
A: 

I have an issue to output this when I add the CDATA attribute on the top like this:

<xsl:output method="xml" indent="yes" cdata-section-elements="school"/>

The output turn to this:

<?xml version="1.0" encoding="utf-8"?>
<schools>
  <school><![CDATA[ shchool5]]><![CDATA[,]]><![CDATA[ shcool4]]><![CDATA[, ]]><![CDATA[ school3]]><![CDATA[, ]]><![CDATA[ school2]]><![CDATA[, ]]><![CDATA[school1]]></school>
</schools>

Is there any things I could do just to have one CDATA to wrap the data like this:

<?xml version="1.0" encoding="utf-8"?>
<schools>
  <school><![CDATA[ shchool5, shcool4,  school3,  school2, school1]]></school>
</schools>
Daoming Yang