xsl-list
[Top] [All Lists]

Figuring out for-group-by

2004-07-08 16:00:33
I am running into trouble doing a transform with for-group-by. I am currently running Saxon 7.9.1 and am in the process of upgrading to 8.0. I thought I would post what I am up to in case my approach is wrong.

I have an XML file that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
   <key>Major Version</key><integer>1</integer>
   <key>Minor Version</key><integer>1</integer>
   <key>Application Version</key><string>4.6</string>
<key>Music Folder</key><string>file://localhost/Volumes/120%20GB/Music/iTunes/iTunes%20Music/</string>
   <key>Library Persistent ID</key><string>4AB531F8615308F0</string>
   <key>Tracks</key>
   <dict>
       <key>35</key>
       <dict>
           <key>Track ID</key><integer>35</integer>
           <key>Name</key><string>Last Time</string>
           <key>Artist</key><string>Fuel</string>
           <key>Album</key><string>Something Like Human</string>
           <key>Genre</key><string>Rock</string>
           <key>Kind</key><string>AIFF audio file</string>
           <key>Size</key><integer>39233574</integer>
            <!-- more key-value pairs -->
       </dict>
        <!-- more dict groups -->
   </dict>
</dict>
</plist>

I have started out like this:

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

<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
<xsl:for-each-group select="plist/dict/dict/dict" group-by="key[string() = 'Artist']/following-sibling::string[1]">
   <xsl:variable name="artist" select="current-grouping-key()"/>
<xsl:for-each-group select="current-group()" group-by="key[string() = 'Album']/following-sibling::string[1]">
     <xsl:variable name="album" select="current-grouping-key()"/>
<xsl:for-each-group select="current-group()" group-by="key[string() = 'Name']/following-sibling::string[1]">
       <xsl:variable name="song" select="current-grouping-key()"/>
       <xsl:element name="song">
         <xsl:attribute name="artist">
           <xsl:value-of select="$artist"/>
         </xsl:attribute>
         <xsl:attribute name="album">
           <xsl:value-of select="$album"/>
         </xsl:attribute>
         <xsl:attribute name="name">
           <xsl:value-of select="$song"/>
         </xsl:attribute>
         <xsl:attribute name="key">
<xsl:value-of select="current-group()/key[string() = 'Track ID']/following-sibling::integer[1]"/>
         </xsl:attribute>
       </xsl:element>
     </xsl:for-each-group>
   </xsl:for-each-group>
 </xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>

In case you are wondering, I am trying to fix my iTunes library which has duplicate entries in it as a result of converting everything to Apple Lossless encoding. Looking at the results I can see that the attribute labelled 'key' gives me all of the track Ids matching the compound key. The fact that there are more than one is the issue. What I would like to do is identify the track Id(s) associated with the entry that has

<key>Kind</key><string>Apple Lossless audio file</string>

within it.  I tried moving up a level in the initial select like this:

<xsl:for-each-group select="plist/dict/dict" group-by="dict/key[string() = 'Artist']/following-sibling::string[1]">

to see if I can see if I can get the enclosing dict element as current-group but it took a long time and gave me nothing.

My main problem is that I am having trouble visualizing what I am working with inside of the inner for-each-group.

Thanks.


<Prev in Thread] Current Thread [Next in Thread>