0

I've got the following XML:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="Test.xslt"?>
<test-results>
    <test-case name="TestCase1" description="Descriptiontext">
        <categories>
            <category name="Dimension linked to measure group" />
        </categories>
    </test-case>
    <test-case name="TestCase2" description="DescriptionText">
        <categories>
            <category name="Dimension linked to measure group" />
        </categories>
    </test-case>
    <test-case name="TestCase3" description="DescriptionText">
        <categories>
            <category name="Default parameters" />
        </categories>
    </test-case>
    <test-case name="TestCase4" description="DescriptionText">
        <categories>
            <category name="Default parameters" />
        </categories>
    </test-case>
    <test-case name="TestCase5" description="DescriptionText">
        <categories>
            <category name="Referential Integrity" />
        </categories>
        <reason>
            <message><![CDATA[Not testable, yet (v1.6.1)]]></message>
        </reason>
    </test-case>
    <test-case name="TestCase6" description="DescriptionText">
        <categories>
            <category name="Referential Integrity" />
        </categories>
        <reason>
            <message><![CDATA[Not testable, yet (v1.6.1)]]></message>
        </reason>
    </test-case>
</test-results>

With the following XSLT I try to use Muenchian grouping to order by category name (ascending) and within each category by test-case name (ascending).

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml">
    <xsl:key name="cases-by-category" match="categories" use="category/@name" />
    <xsl:template match="test-case">
        <xsl:for-each select="categories[count(. | key('cases-by-category', category/@name)[1]) = 1]">
            <xsl:sort select="category/@name" />
            <xsl:value-of select="category/@name" /><br/>
            <xsl:for-each select="key('cases-by-category', category/@name)">
                <xsl:sort select="//test-case/@name" />
                <xsl:value-of select="//test-case/@name"/><br/>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

However, what I get is this:

Dimension linked to measure group
TestCase1
TestCase1
Default parameters
TestCase1
TestCase1
Referential Integrity
TestCase1
TestCase1

The number of test cases for each category is correct, but the sorting doesn't get applied and the first test-case name is always used. How can I fix this?

honk
  • 9,137
  • 11
  • 75
  • 83
thuss
  • 3
  • 2

1 Answers1

0

Given <xsl:key name="cases-by-category" match="categories" use="category/@name" /> the expression key('cases-by-category', category/@name) gives you a node-set of categories elements, if you want to sort them by the parent then I think you want to use <xsl:sort select="../@name" />.

I also think having

<xsl:template match="test-case">
    <xsl:for-each select="categories[count(. | key('cases-by-category', category/@name)[1]) = 1]">

looks odd as you would process the categories of every matched test-case element, it seems more likely you want

<xsl:template match="test-results">
    <xsl:for-each select="test-case/categories[count(. | key('cases-by-category', category/@name)[1]) = 1]">

instead.

Here is a complete sample:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml">

    <xsl:output indent="yes"/>

    <xsl:key name="cases-by-category" match="categories" use="category/@name" />

    <xsl:template match="/">
      <html>
        <body>
          <xsl:apply-templates/>
        </body>
      </html>
    </xsl:template>

    <xsl:template match="test-results">
      <xsl:for-each select="test-case/categories[count(. | key('cases-by-category', category/@name)[1]) = 1]">
            <xsl:sort select="category/@name" />
            <xsl:value-of select="category/@name" /><br/>
            <xsl:for-each select="key('cases-by-category', category/@name)">
                <xsl:sort select="../@name" />
                <xsl:value-of select="../@name"/><br/>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

When I run that with Saxon 6.5 against your input I get the following result:

<html xmlns="http://www.w3.org/1999/xhtml">
   <body>Default parameters<br/>TestCase3<br/>TestCase4<br/>Dimension linked to measure group<br/>TestCase1<br/>TestCase2<br/>Referential Integrity<br/>TestCase5<br/>TestCase6<br/>
   </body>
</html>
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • The hint to "../@name" instead of "test-case/@name" worked a charme, substituting this in both the sort and value-of tags leads to all test-case names being displayed correctly in alphabetic order. Using test-results leads to nothing being displayed at all though. The only thing left that bugs me is the sorting of the categories (first sort). As of now, I'm doing it exactly the same way as the second one (the now-working-one), but the sort command is seemingly getting ignored... – thuss Aug 14 '14 at 18:57
  • I still think my second suggestion is vital to get the grouping and sorting you want. – Martin Honnen Aug 14 '14 at 20:21
  • May very well be, I'll give it another ago when I get around to it. If I can make it work somehow, I'll make sure to leave a comment. But thanks so far, Martin! – thuss Aug 15 '14 at 07:15
  • @thuss, I have included a complete XSLT sample with the suggestions I made and the output I get. – Martin Honnen Aug 15 '14 at 08:27