xsl-list
[Top] [All Lists]

[xsl] Sort by one attribute & use Muenchian technique to group by another attribute?

2009-06-10 12:43:46
Hello,

I am using XSLT 1.0 - I cannot upgrade to 2.0 at this time.  If the author of 
Saxon 9.0 would upload the releases to the central maven2 repository, myself 
and many more users might be able to do that.  Hint hint if he is reading this. 
 =)

Processor details:
Name: org/apache/xalan
Comment: Main Xalan engine implementing TrAX/JAXP
Specification-Title: Java API for XML Processing
Specification-Vendor: Sun Microsystems Inc.
Specification-Version: 1.2
Implementation-Title: org.apache.xalan
Implementation-Version: 2.6.0

Anyway, I could really use some help or guidance here.  I have two sets of 
nodes that are intermixed - I need to output them ordered by a sort order 
attribute, and group them by a key attribute such that the key only shows up 
when it changes from the previously sorted item.  Here's a simplified example:

Test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="Test.xsl" type="text/xsl"?>

<root>
                <red order="1" key="F" text="red 1 B" />
                <red order="3" key="F" text="red 3 B" />
                <red order="4" key="C" text="red 4 C" />
                <red order="6" key="D" text="red 6 D" />
                <red order="9" key="E" text="red 9 E" />
                <red order="10" key="F" text="red 10 F" />
                <blue order="2" key="B" text="blue 2 B" />
                <blue order="5" key="D" text="blue 5 D" />
                <blue order="7" key="D" text="blue 7 D" />
                <blue order="8" key="E" text="blue 8 E" />
                <blue order="11" key="F" text="blue 11 F" />
                <blue order="12" key="G" text="blue 12 G" /> </root>

Expected output:
F:
red 1 B
B:
blue 2 B
F:
red 3 B
C:
red 4 C
D:
blue 5 D
red 6 D
blue 7 D
E:
blue 8 E
red 9 E
F:
red 10 F
blue 11 F
G:
blue 12 G
 
Notice how @order is how they are sorted there, and the @key is only output 
when it is different from the previous one.
 

Using this stylesheet, I've been able to produce something *close but still a 
ways off. 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
        
         <xsl:key name="keyRedBlue" match="red|blue" use="@key"/>
         
         <xsl:template match="root">
               <xsl:apply-templates select="(red|blue)[generate-id() = 
generate-id(key('keyRedBlue', @key))]" mode="distinct-start">
                       <xsl:sort select="@order" data-type="number" />
               </xsl:apply-templates>
        </xsl:template>
        
        <xsl:template match="red|blue" mode="distinct-start">
               <xsl:value-of select="@key" />:<br />
               <xsl:apply-templates select="key('keyRedBlue', @key)">
                       <xsl:sort select="@order" data-type="number" />
               </xsl:apply-templates>
        </xsl:template>
                
        <xsl:template match="red">
               <xsl:value-of select="@text" /><br />
        </xsl:template>
        
        <xsl:template match="blue">
               <xsl:value-of select="@text" /><br />
        </xsl:template>
</xsl:stylesheet>


produces:

F:
red 1 B
red 3 B  < WRONG
red 10 F
blue 11 F
B:
blue 2 B
C:
red 4 C
D:
blue 5 D
red 6 D
blue 7 D
E:
blue 8 E
red 9 E
G:
blue 12 G

So how can I do this?  Is it even possible?  Previous-sibling isn't an option 
since they are not ordered in the document.  I am not willing to use 2 xsl 
sheets for this.  A brute-force style for-each in the leaf templates could go 
and check the previous sorted one's key I guess, but that is pretty lousy.  If 
I could just change the value of an xsl:variable this would have not even 
required any thought, but I understand that is done for parser efficiency so I 
am semi-ok with that.  And if there were any real options for xslt 2.0 in java 
we could move to that and use the new group features.

Thanks for reading and any help is tremendously appreciated!
-John


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--