简体   繁体   中英

XSLT 1.0 Grouping of parent node grouped by multiple child nodes

I'm trying to group based on multiple child nodes and then display the parent nodes grouped by the child nodes. I've shrunk down the examples a bit, but I hope you get the idea. Now I've got this working in XSL 2.0, but found out I can only use 1.0 in this application. I've been reading up on the Muenchian grouping method but can't seem to figure it out.

This is (part of) the XML:

<Persons>
    <Person PersonID="3987">
        <Desks>
            <Desk Name="10" Active="true">
            </Desk>
            <Desk Name="11" Active="true">
            </Desk>
        </Desks>
    </Person>
    <Person PersonID="3883">
        <Desks>
            <Desk Name="10" Active="true">
            </Desk>
            <Desk Name="11" Active="true">
            </Desk>
            <Desk Name="12" Active="true">
            </Desk>
            <Desk Name="13" Active="true">
            </Desk>
        </Desks>
    </Person>
</Persons>

This is how far I got on the Muenchian grouping method:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:key name="persons-per-desk" match="Person" use="Desks/Desk/@Name"/>

    <xsl:template match="Person[generate-id() = generate-id(key('persons-per-desk', Desks/Desk/@Name)[1])]">
        <Desk>
            <xsl:copy-of select="Desks/Desk/@Name" />
            <Person>
                <xsl:copy-of select="key('persons-per-desk', Desks/Desk/@Name)/@PersonID" />
            </Person>
        </Desk>
    </xsl:template>

    <xsl:template match="Person" />
</xsl:stylesheet>

What I hope to expect:

<Desk Name="10">
   <Person PersonID="3883"/>
   <Person PersonID="3987"/>
</Desk>
<Desk Name="11">
   <Person PersonID="3883"/>
   <Person PersonID="3987"/>
</Desk>
<Desk Name="12">
   <Person PersonID="3883"/>
</Desk>
<Desk Name="13">
   <Person PersonID="3883"/>
</Desk>

What I get:

<Desk Name="11">
   <Person PersonID="3883"/>
</Desk>

Any help would be greatly appreciated.

You are trying to group persons by their desk name/s - but what you need to do is group desks by their name first, then list the persons having a desk in each group:

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:key name="desk-by-name" match="Desk" use="@Name"/>

<xsl:template match="/Persons">
    <Desks>
        <!-- create a grpup for each distinct desk name -->
        <xsl:for-each select="Person/Desks/Desk[generate-id() = generate-id(key('desk-by-name', @Name)[1])]">
            <Desk Name="{@Name}">
                <!-- list the persons having desks in this group -->
                <xsl:for-each select="key('desk-by-name', @Name)/ancestor::Person">
                    <Person PersonID="{@PersonID}"/>
                </xsl:for-each>
            </Desk>
        </xsl:for-each>
    </Desks>
</xsl:template>

</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM