2

I have an xml document that looks like this.

<?xml version="1.0"?>
<services>
    <service sn="1" family="2 Week Wait">
    <service_name>2 Week Wait Dermatology</service_name>
    <speciality>2 Week Wait</speciality>
    <clinic_types>2 Week Wait Skin</clinic_types>
    <tag>Malignant neoplasm of skin , Pigmented skin lesion </tag>
</service>

I've managed to get everything how I want but for one last tweak I'd like to have the Comma Separated Values display as a unordered list.

I'm using this line of XSL to output the list,

<ul>
     <li>
           <xsl:value-of select="translate(tag,',','<![CDATA[</li><li>]]>')" disable-output-escaping="yes" />
     </li>
<ul>

I'm getting an error saying that the resulting XML isn't formatted properly. I've tried to replace the replacement section with other stuff and it's worked. I've also tried using the HTML ASCII codes for the tags with no luck so I'm really confused with what I'm doing wrong.

Any help appreciated, Thanks

  • possible duplicate of [Does xslt have split() function?](http://stackoverflow.com/questions/3336424/does-xslt-have-split-function) or http://stackoverflow.com/questions/584082/xslt-best-way-to-split-and-render-comma-separated-text-as-html or http://stackoverflow.com/questions/136500/does-xslt-have-a-split-function . Besides the wrong approuch with `fn:traslate()`: it replaces one to one character only. –  Oct 29 '10 at 12:33
  • I managed to get my solution via the first link, thank you very much. I'm new to XSL so it's a rookie mistake –  Oct 29 '10 at 13:22

2 Answers2

2

XSLT is XML; the select expression is embedded inside an attribute value so it must apply another round of XML-escaping. Since a CDATA section can't live in an attribute value, that has to be applied manually:

<xsl:value-of select="translate(tag,',','&lt;/li>&lt;li>')" disable-output-escaping="yes" />

However, applying disable-output-escaping to the output of translate is questionable: what if the text had < or & characters in it? You'd be turning text content into active markup, with validity and potential security problems.

Normally it would be better to add markup from XSLT itself. You can split a string in XSLT 2.0 using the tokenize function:

<ul>
    <xsl:for-each select="tokenize(tag,',')">
        <li><xsl:value-of select="."/></li>
    </xsl:for-each>
</ul>

(If you're using XSLT 1.0 this has to be done as a recursive template using substring_before/after, which is a pain.)

bobince
  • 528,062
  • 107
  • 651
  • 834
  • 'tokenize' is not a valid XSLT or XPath function.-->tokenize(tag,',')<-- –  Oct 29 '10 at 10:47
  • oops sent too soon, yeah looks like I have to do the recursive template thing. –  Oct 29 '10 at 10:48
  • Shame! See [this answer](http://stackoverflow.com/questions/136500/does-xslt-have-a-split-function/141022#141022) for an example of how it's done. – bobince Oct 29 '10 at 11:01
-1
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:template match="tag">
        <ul>
                <xsl:for-each select="tokenize(.,',')">
                    <li><xsl:value-of select="."/></li>
                </xsl:for-each>
            </ul>
</xsl:template>

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
  • 2 Week Wait Dermatology 2 Week Wait 2 Week Wait Skin
      • Malignant neoplasm of skin
      • Pigmented
      • skin
      • lesion
    abhay
    – Abhay kumar Gupta Jul 24 '21 at 16:12
  • Please do not repeat an answer already given. Not to mention that your stylesheet declares `version="1.0" ` but requires XSLT 2.0 (as was correctly stated in the other answer). – michael.hor257k Jul 24 '21 at 16:42