a quick question on using xslt 1.0 might able me with.i have input xml looks below
<root> <firstname>bob</firstname> <lastname>marley</lastname> <id>bm1234</id> <songs> <song> <emptyelements></emptyelements> <songname>no woman no cry</songname> <year>1974</year> <album></album> <studio></studio> <rating></rating> </song> </songs> </root>
the output needs like
<root> <firstname>bob</firstname> <lastname>marley</lastname> <id>bm1234</id> <songs> <song> <emptyelements>album, studio, rating</emptyelements> <songname>no woman no cry</songname> <year>1974</year> </song> </songs> </root>
so comma separated list of empty elements emptyelements tag.
or simply:
xslt 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/> <!-- identity transform --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="song"> <xsl:copy> <emptyelements> <xsl:for-each select="*[not(node() or self::emptyelements)]"> <xsl:value-of select="name()"/> <xsl:if test="position()!=last()"> <xsl:text>, </xsl:text> </xsl:if> </xsl:for-each> </emptyelements> <xsl:apply-templates select="*[node()]"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
note:
this solution proudly uses last()
function. there no performance issues related using function.
the xpath specification states:
the last function returns number equal context size expression evaluation context.
and xslt specification tells that:
expression evaluation occurs respect context. ... context consists of:
• node (the context node)
• pair of non-zero positive integers (the context position , context size)
...
the idea processor go , count nodes in current node list, again , again, each node in list preposterous. once context has been established (by calling either xsl:for-each
or xsl:apply-templates
), context size known , isn't going change.
this conclusion can put test: using list of 10k items, no discernible difference found when evaluating:
<xsl:for-each select="item"> <xsl:value-of select="position()!=last()"/> </xsl:for-each>
against:
<xsl:for-each select="item"> <xsl:value-of select="not(position() = 1)"/> </xsl:for-each>
(tested libxslt, xalan , saxon).