XSL: translate() with html in replacing string
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开发者_JS百科 help appreciated, Thanks
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,',','</li><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.)
<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>
精彩评论