Reputation: 11
I want to simply have a textual output that shows the song title and the number of the weeks that ranked #1. But, I don't know how to use count in xslt. Can anyone help me find out what's wrong with my code? The codes I have right now doesn't have any output.
<?xml version='1.0'?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output encoding="UTF-8" omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:for-each select="popular-recordings-dataset/recording">
<xsl:sort select="count(//rank[. = '1'])" order="descending"/>
<xsl:value-of select="concat(title, ' / ', count(//rank[. = '1']),'
')" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Views: 205
Reputation: 243579
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:apply-templates select="recording">
<xsl:sort select="count(week/rank[. = 1])"
data-type="number" order="descending"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="recording">
<xsl:value-of select=
"concat(title, ' / ', count(week/rank[. = 1]), '
')"/>
</xsl:template>
</xsl:stylesheet>
when applied on the following XML document (none provided in the question !!!):
<popular-recordings-dataset>
<recording>
<title>Song1</title>
<week no="23">
<rank>1</rank>
</week>
<week no="24">
<rank>2</rank>
</week>
</recording>
<recording>
<title>Song2</title>
<week no="22">
<rank>1</rank>
</week>
<week no="24">
<rank>1</rank>
</week>
<week no="25">
<rank>1</rank>
</week>
</recording>
<recording>
<title>Song3</title>
<week no="21">
<rank>1</rank>
</week>
<week no="26">
<rank>1</rank>
</week>
</recording>
</popular-recordings-dataset>
produces the wanted, correct result:
Song2 / 3
Song3 / 2
Song1 / 1
Explanation: The problem with your code is in using this expression:
count(//rank[. = '1'])
The argument to count()
is an absolute XPath expression (starts with /
), therefore it selects all rank
elements in the document with value equal to 1
. This means that this expression doesn't depend on and vary with the current rank
element and remains the same for all rank
elements. Sorting on a constant doesn't change the initial ordering of the node-set -- as you have witnessed.
Solution:
Change:
count(//rank[. = '1'])
to:
count(.//rank[. = '1'])
But better, if the structure of the XML document is known in advance, then try to avoid using the //
pseudo-operator, which can be very inefficient.
Upvotes: 1