XSLT հրահանգաշար iTunes XML- ից հավաքածուների  ցանկ ստեղծելու համար

Երբ ես iPod ունեցա, հասկացա, որ  iTunes  ծրագրում հասանելի ցուցակագրված գործիքները առանձնապես հզոր չեն (Չնայած հոյակապ ինտերակտիվ ինտերֆեյսին) և ես չկարողացա ստանալ ալբոմներ հակիրճ ամփոփագիրը: Քանի որ iTunes-ը ստեղծում է իր գրադարանները XML-ով, ես օգտագործում եմ XSLT-ը իմ ճաշակին համապատասխան ցուցակ ստեղծելու համար: Քանի որ ես նախընտրում եմ լսել հավաքածուներ, քան անհատ երգեր, ապա ես սիրում եմ ըստ տեսակների / ժանրերի խմբավորված հավաքածուներ:

Այս հրահանգաշարը կիարռելու համար պետք է պահպանել ներքոնշյալ albumList.xml-ը  և albumList.xsl-ը ձեր  My Music/iTunes  պահոցում, ապա բացել albumList.xml Internet Explorer 6+ -ում կամ Mozilla Firefox-ում (IE5 –ը չի աշխատում; այլ բրաուզերներ չեմ փորձարկել):

 iTunes XML-ի <<գույքի ցանկ>>

iTunes-ի գրադարանները ձևավորվում են որպես XML iTunes Music Library.xml կոչվող ֆայլում: Այն կիրառում է համընդհանուր XML լեզուն ճանաչված որպես <<գույքի ցանկ>> կամ plist, որը պահպանում է տեղեկությունը որպես հիմնական / արժեքավոր զույգեր: Ավելի, քան հարմարեցված նկարագրվող երգերին, այն կարելի է կիրառել այլ գործիքների գույքերը: Ահա թե ինչ տեսք ունի XML-ը.

<plist version="1.0">
<dict>
<key>Tracks</key>
<dict>
<key>638</key>
<dict>
<key>Track ID</key><integer>638</integer>
<key>Name</key><string>Take Me To The River</string>
<key>Artist</key><string>Talking Heads</string>
<key>Composer</key><string>Al Green &#38; M. Hodges</string>
<key>Album</key><string>Stop Making Sense</string>
<key>Genre</key><string>Alternative &#38; Punk</string>
        ... etc ...
</dict>
</dict>
</dict>
</plist>

Սա նշանակում է, որ հավաքածուի անունը գտնելու կամ ասելու համար մենք պետք է համապատասխանեցնենք լարը հավաքածուի` անմիջապես նախորդող նմանատիպ ստեղնին.

string[preceding-sibling::key[1]='Album']

Այսինքն, <<լար>> տարրը, որտեղ առաջին <<ստեղն>> տարրը գործող նմանատիպ առանցքում ունի <<հավաքածուի>> արժեք:

Թեեւ սա հարմար ընդհանուր նշանակության XML լեզու է, այն միանշանակ շատ ավելի բարդ է շահարկե, քան  ներկայիս ցուցակին հարմարեցված XML լեզուն, այնպես որ  խոր շունչ քաշեքև շարունակեք:

Հավաքածուի ցուցակի ձեռքբերում

iTunes XML-ը երգերի ցանկ է: Երգերի հավաքածուն ոչ այլ ինչ է, քան երգի հատկանիշ, ուստի ցանկացած երգի հայտնվելուն պես հավաքածուն անուն ձեռք կբերի: Ուստի հավաքածուների հստակ ցուցակն ունենալու համար ես կիրառում եմ  <xsl:key>  տարրով ձեռք բերվող ավելի խելացի գործիք և key() և generate-id() գործառույթներ:

Մյուսները բացատրում են <xsl:key>-ի կիրառությունը ավելի լավ,, քան ես, բայց հակիրչ լինելու համար նշեմ,  <xsl:key> տարրը ստեղծում է երգերը ներկայացնող <dict> հանգույցների ցանկ: Հետո <xsl:for-each>-ն ընտրում է <dict> (օրինակ երգ) տարրը, որտեղ ստեղծված id-ն համընկնում է  () գործառույթով ստեղծված առաջին հանգույցի id-ին: Բարդ է նաև ինձ համար: Ստեղծված հավաքածուի ցուցակի ոճը հետևյալն է.

<xsl:key name="songsByAlbum" match="dict"
  use="string[preceding-sibling::key[1]='Album']"/>

<xsl:template match="/plist/dict/dict">
<html>
<body>
<table>

<xsl:for-each select="dict[generate-id(.)=
            generate-id(key('songsByAlbum',string)[1])]">
<xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
<tr>
<td><xsl:value-of select="string[preceding-sibling::key[1]='Album']"/></td>
<td><xsl:value-of select="string[preceding-sibling::key[1]='Artist']"/></td>
</tr>
</xsl:for-each>

</table>
</body>
</html>
</xsl:template>

Սա բարդություններ է առաջացնում ժողովածուներում: Այն կվերցնի որևէ ժողովածուի առաջին երգի հեղինակի անվանումը, որը առաջին հայացքից տարօրինակ կթվա: Սա պահպանելու համար ես կիրառում եմ ներքոնշյալ  <<ժողովածուի մի մասը>> .

<xsl:key name="songsByAlbum" match="dict"
  use="string[preceding-sibling::key[1]='Album']"/>

<xsl:template match="/plist/dict/dict">
<html>
<body>
<table>

<xsl:for-each select="dict[generate-id(.)=generate-id(key('albums',string)[1])]">
<xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
<tr>
<td><xsl:call-template name="albumName"/></td>
<td><xsl:call-template name="artistName"/></td>
</tr>
</xsl:for-each>

</table>
</body>
</html>
</xsl:template>

<xsl:template name="albumName">
<xsl:value-of select="string[preceding-sibling::key[1]='Album']"/>
</xsl:template>

<xsl:template name="artistName">
<xsl:choose>
<xsl:when test="true[preceding-sibling::key[1]='Compilation']">
<i>Compilation</i>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="string[preceding-sibling::key[1]='Artist']"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Ես բաժանել եմ հիմնական կաղապարը առանձինկաղապարների հավաքածուների և հեղինակների համար: Հնարավոր է  XSLT-ը բարդ է միշտ կիրառելու համար, ուստի ես նախընտրում եմ ստեղծել հնարավորինս շատ կաղապարներ.

Ըստ ժանրերի տեսակավորված հավաքածուների ցանկ

Միակ դժվարությունն այն է, թե ինչպես են այս երգերի համակցվում իրար: Ես չեմ ցանկանա միաձուլել, օրինակ, St Matthew Passion-ը Stop Making Sense-ի հետ:  

Ժանրերով հավաքածուները տեսակավորելու համար ես կիրառում եմ Սթիվ Մուենխի մշակած մեթոդը` Oracle’s ‘XML Technical Evangelist’-ը  զուդորդված ‘Muenchian grouping-ով:

Կրկին, մոյւսներն ավելի լավ են սա նկարագրում, որպես հավելու նշեմ (եթե կցանկանաք XSL գործարկմանը կցանկանաք հետևել), որ այն կիրառում է  XSL գործիքների generate-id ()  գործառույթը ժանրի երգի վրա և հավաքածուներում, իսկ այնտեղ, որտեղ կաղապարը կոչվում է albumsInGenre , գործող կոնտեքստում առաջին <dict> երգը հայտնվում է յուրաքանչյուր ժանրում:

albumsInGenre կաղապարում նույն մեթոդն է կիրառվում յուրաքանչյուր հավաքածուի մեջ առաջին երգը ձեռք բերելու համար հավաքածուն և հեղինակին  անվանելո նպատակով: Ես նաև կիրառում եմ հավելյալ ստորոգելի այս հանգուցավորված ժանրերը զտելու համար` կցելով այն կաղապարին որպես հավելյալ հատկանիշ:

(Կյանքն ավելի հեշտ կլիներ XSLT 2.0-ով, որը կունենար անհատական տարր յուրաքանչյուր խմբի համար).

Սա հետևյալ տեսքը կունենար

<xsl:key name="songsByAlbum" match="dict"
  use="string[preceding-sibling::key[1]='Album']"/>
<xsl:key name="songsByGenre" match="dict" 
  use="string[preceding-sibling::key[1]='Genre']"/>


<xsl:template match="/plist/dict/dict">
<html>
<body>
<table>

<xsl:for-each select="dict[generate-id(.)=
            generate-id(key('songsByGenre',string)[1])]">
<xsl:sort select="string[preceding-sibling::key[1]='Genre']"/>
<xsl:for-each select="key('songsByGenre',string)[1]">
<xsl:call-template name="albumsInGenre">
<xsl:with-param name="genre" 
                  select="string[preceding-sibling::key[1]='Genre']"/>
</xsl:call-template>
</xsl:for-each>
</xsl:for-each>

</table>
</body>
</html>
</xsl:template>


<xsl:template name="albumsInGenre">
<xsl:param name="genre"/>

<tr><td colspan='3'><b><xsl:value-of select="$genre"/></b></td></tr>

<xsl:variable name="song" select="/plist/dict/dict/dict"/>
<xsl:for-each select="$song[generate-id(.)=
      generate-id(key('songsByAlbum',string[preceding-sibling::key[1]='Album'])[1])]">
<xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
<xsl:for-each select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])
        [string[preceding-sibling::key[1]='Genre']=$genre][1]">
<tr>
<td> </td>
<td><xsl:call-template name="albumName"/></td>
<td><xsl:call-template name="artistName"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</xsl:template>

Արդյունքում ստեղծված հավաքածուն կունենար հետևյալ տեսքը

 Էլեկտրոնիկա/ պար​
  Boulevard St. Germain
  Dehli9 Tosca
  On Land Brian Eno
 Ջազ​
  Madar Jan Garbarek
  The Hot Fives & Sevens  Louis Armstrong & The Hot Five

Եթե նախընտրում եք ունենալ առանձին հավաքածու iPod-ի վրա iTunes-ից դուրս, պետք է ավելացնեք հավելյալ ներքին գործառույթ, որը հետևյալ տեսքը կունենա

<xsl:for-each select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])
        [string[preceding-sibling::key[1]='Genre']=$genre]
        [not(true[preceding-sibling::key[1]='Disabled'])][1]">

Ուղեգծային ժամանակի ավելացում

Սա ես փորձարկել եմ յուրաքանչյուր հավաքածուի տևողությունը ստուգելու նպատակով: Յուրաքանչյուր երգի տևողությունը պահպանվում է (միլիվայրկյաններով) հակառակ Total Time key-ի, ուստի կաղապարը ունի հետևյալ տեսքը.

<xsl:template name="iTunesTimeAlbum">
<xsl:variable name="tracksInAlbum" 
      select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])"/>
<xsl:variable name="t" 
      select="sum($tracksInAlbum/integer[preceding-sibling::key[1]='Total Time'])"/>
<xsl:call-template name="formatTime">
<xsl:with-param name="t" select="$t"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="formatTime">
<xsl:param name="t"/>
<xsl:if test="$t != 0">
<xsl:variable name="h" select="floor(($t div (1000*60*60)))"/>
<xsl:variable name="m" select="floor(($t div (1000*60)) mod 60)"/>
<xsl:variable name="s" select="floor(($t div 1000) mod 60)"/>
<xsl:if test="$h != 0"><xsl:value-of select="$h"/>h</xsl:if>
<xsl:value-of select="format-number($m,'00')"/>m
<xsl:value-of select="format-number($s,'00')"/>s
</xsl:if>
</xsl:template>

Կրկին, եթե դուք ցանկանում եք iTunes գրադարանի երգերի տևողության փոխարեն ունենալ iPod-ի երգերի տևողությունը, ապա (եթե հավաքածուից մի քանիսն եք ընտրել iPod տեղափոխելու համար) հետևյալ գործառույթը պիտի կիրառվի.

<xsl:variable name="t"
      select="sum($tracksInAlbum/integer[preceding-sibling::key[1]='Total Time']
      [not(../true[preceding-sibling::key[1]='Disabled'])])"/>

Այս կաղապարը կբացահայտի iTunes գրադարանի երգերի տևողությունը (կամ iPod-ի):

<xsl:template name="iTunesTimeTotal">
<xsl:variable name="t" 
      select="sum(dict/integer[preceding-sibling::key[1]='Total Time'])"/>
<xsl:call-template name="formatTime">
<xsl:with-param name="t" select="$t"/>
</xsl:call-template>
</xsl:template>

Եթե ցանկանում եք ունենալ սկավառակի վրա երգերի տևողությունևը, այս կարելի է ձեռք բերել Size key-ով.

<xsl:template name="iTunesSizeTotal">
<xsl:variable name="s" select="sum(dict/integer[preceding-sibling::key[1]='Size'])"/>
<xsl:value-of select="floor($s div (1000*1000)) div 1000"/>GB
</xsl:template>

Բրաուզերում ցուցակի ստեղծում

XML/XSLT գործիքները կիրառելու փոխարեն կարող ենք անմիջապես ցուցակ բացել  բրաուզերում: Ես սա անում եմ ստեղծելով ‘wrapper’ XML ֆայլ, որը հնարավորւթյուն է տալիս հասկանալ որ ոճն է համապատասխանում յուրաքանչյուր XML ֆայլին կիրառելով <?xml-stylesheetգործարկվող հրահանգներն ու <incl> տարրը:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="albumList.xsl" type="text/xsl"?>
<wrapper>
<incl file="iTunes Music Library.xml"/>
</wrapper>

Հետո ես տեղադրում եմ կաղապարը XSL –ում, որը համապատասխանում է  <wrapper> տարրին, որ ես տեղադրել եմ ներմուծված XML ֆայլում, կիրառում կաղապարը ներմուծված XML ֆայլում.

<xsl:template match="/wrapper">
<xsl:apply-templates select="document(incl/@file)"/>
</xsl:template>

Սա կիրառելի է ցանկացած գործող բրաուզերում; փորձարկել եմ Internet Explorer (6.0+)-ում և  Firefox-ում.

Նշում` այլ պայմանական կառույցներում այլընտրանքային մոտեցումներ կարող են կիրառվել p-list XML-ը գործարկելւո համար, որը բացատրված է www.xmldatabases.org/WK/blog/1086?t=item, www.xmldatabases.org/WK/blog/1086?t=itemորը հետապես ավելի պարզ է, քան XSLT-ը:  Ես կիրառում եմ նմանատիպ կառույցներ մեկ քայլով ցուցակներ ստեղծելու նպատակով:


Այս ամենը ներքնշյալ ոճում համակցված է: Այն ստեղծում է ավելի լայն ոճային ցանկ, սակայն վերը նշված տեղեկության կիրառմամբ դուք կարող եք առանձնացնել այս գործառույթներն ու կիրառել առանձին-առանձին:

… հիմա ես ունեմ հավաքածուների հղումների ցանկ իմ iPod-ում:

Սա հիմնական կամ ամբողջական ձևում կիրառելու համար պահպանեք My Music/iTunes-ի ներքևի հատվածում ցուցադրված albumList.xml and albumList.xsl –ը, ձեր բրաուզերում (IE6 կամ Firefox).  բացեք albumList.xml: Եթե դուք ցանկանում եք հարմարեցնել դասավորությունը, ինչպես նաեւ վերը նշված ուղեցույցները,  դուք կարող եք  խառնել եւ  համապատասխանեցնել բաղադրիչները ըստ պահանջի: դուք կարող եք կիրառել այս կաղապարները (առանց երաշխիքի կամ ենթադրության) անհատական նպատակներով: Ցանկացած հարցերի դեպքում դիմեքդիմել:

Այս էջը թարգմանել է Ջովանա Միլուտինովիչը  Սերբերեն-խորվաթերեն Սերբերեն-խորվաթերեն WebHostingGeeks-ից


Ֆայլ albumList.xml (specifies to apply albumList.xsl to iTunes Music Library.xml):

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="albumList.xsl" type="text/xsl"?>
<wrapper>
<incl file="iTunes Music Library.xml"/>
</wrapper>

Ֆայլ albumList.xsl basic version (lists name & artist of albums on iPod):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- (c) Chris Veness 2005 -->
<xsl:output method="html" encoding="UTF-8" indent="yes"/>

<!-- match the wrapper and apply templates to the <incl> xml file -->
<xsl:template match="/wrapper">
<xsl:apply-templates select="document(incl/@file)/plist/dict/dict"/>
</xsl:template>


<xsl:key name="songsByGenre" match="dict" use="string[preceding-sibling::key[1]='Genre']"/>
<xsl:key name="songsByAlbum" match="dict" use="string[preceding-sibling::key[1]='Album']"/>


<xsl:template match="dict">
<html>
<head>
<title>iPod Album Listing</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<table>

<xsl:for-each select="dict[generate-id(.)=generate-id(key('songsByGenre',string)[1])]">
<xsl:sort select="string[preceding-sibling::key[1]='Genre']"/>
<xsl:for-each select="key('songsByGenre',string)[1]">
<xsl:call-template name="albumsInGenre">
<xsl:with-param name="genre" select="string[preceding-sibling::key[1]='Genre']"/>
</xsl:call-template>
</xsl:for-each>
</xsl:for-each>

</table>
</body>
</html>
</xsl:template>


<xsl:template name="albumsInGenre">
<xsl:param name="genre"/>

<!-- genre header -->
<tr><td colspan='3'><b><xsl:value-of select="$genre"/></b></td></tr>

<!-- output each album in genre -->
<xsl:variable name="song" select="/plist/dict/dict/dict"/>
<xsl:for-each select="$song[generate-id(.)=
        generate-id(key('songsByAlbum',string[preceding-sibling::key[1]='Album'])[1])]">
<xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
<xsl:for-each select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])
          [string[preceding-sibling::key[1]='Genre']=$genre]
          [not(true[preceding-sibling::key[1]='Disabled'])][1]">
<tr valign='top'>
<td width='20'> </td>
<!-- the album name: -->
<td><xsl:value-of select="string[preceding-sibling::key[1]='Album']"/></td>
<!-- the artist: -->
<td>
<xsl:choose>
<xsl:when test="true[preceding-sibling::key[1]='Compilation']">
<i>Compilation</i>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="string[preceding-sibling::key[1]='Artist']"/>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Ֆայլ albumList.xsl full version (includes complete iTunes library with times & totals):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- (c) Chris Veness 2005-2006 -->
<xsl:output method="html" encoding="UTF-8" indent="yes"/>


<!-- match the wrapper and apply templates to the <incl> xml file -->
<xsl:template match="/wrapper">
<xsl:apply-templates select="document(incl/@file)/plist/dict/dict"/>
</xsl:template>


<xsl:key name="songsByGenre" match="dict" use="string[preceding-sibling::key[1]='Genre']"/>
<xsl:key name="songsByAlbum" match="dict" use="string[preceding-sibling::key[1]='Album']"/>


<xsl:template match="dict">
<html>
<head>
<title>iTunes Album Listing</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style type='text/css'> td { vertical-align: top; padding-right: 1em; } </style>
</head>
<body>
<table>

<xsl:for-each select="dict[generate-id(.)=generate-id(key('songsByGenre',string)[1])]">
<xsl:sort select="string[preceding-sibling::key[1]='Genre']"/>
<xsl:for-each select="key('songsByGenre',string)[1]">
<xsl:call-template name="albumsInGenre">
<xsl:with-param name="genre" select="string[preceding-sibling::key[1]='Genre']"/>
</xsl:call-template>
</xsl:for-each>
</xsl:for-each>

<!-- totals -->
<tr>
<td colspan='4' style='color: gray'><b>Total</b></td>
<td style='color: gray' align='right'><xsl:call-template name="iPodTimeTotal"/></td>
<td style='color: gray' align='right'><xsl:call-template name="iTunesTimeTotal"/></td>
</tr>
<tr>
<td colspan='4'> </td>
<td style='color: gray' align='right'><xsl:call-template name="iPodSizeTotal"/></td>
<td style='color: gray' align='right'><xsl:call-template name="iTunesSizeTotal"/></td>
</tr>

</table>
</body>
</html>
</xsl:template>


<xsl:template name="albumsInGenre">
<xsl:param name="genre"/>

<tr>  <!-- genre header -->
<td colspan='4'><b><xsl:value-of select="$genre"/></b></td>
<td align='right' style='color: gray'><i>iPod</i></td>
<td align='right' style='color: gray'><i>iTunes</i></td>
</tr>

<xsl:variable name="song" select="/plist/dict/dict/dict"/>
<xsl:for-each select="$song[generate-id(.)=
        generate-id(key('songsByAlbum',string[preceding-sibling::key[1]='Album'])[1])]">
<xsl:sort select="string[preceding-sibling::key[1]='Album']"/>
<xsl:for-each select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])
          [string[preceding-sibling::key[1]='Genre']=$genre]
          [1]">
<!--  for albums on iPod only, add
                [not(true[preceding-sibling::key[1]='Disabled'])] -->
<tr>
<td> </td>
<td><xsl:call-template name="album"/></td>
<td><xsl:call-template name="artist"/></td>
<td align='right'><xsl:call-template name="iPodTimeAlbum"/></td>
<td align='right'><xsl:call-template name="iTunesTimeAlbum"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
<tr><td colspan='6'>&#160;</td></tr>  <!-- space between genres -->
</xsl:template>


<xsl:template name="album">
<xsl:value-of select="string[preceding-sibling::key[1]='Album']"/>
</xsl:template>


<xsl:template name="artist">
<xsl:choose>
<xsl:when test="true[preceding-sibling::key[1]='Compilation']">
<i>Compilation</i>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="string[preceding-sibling::key[1]='Artist']"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>


<xsl:template name="iPodTimeAlbum">
<xsl:variable name="tracksInAlbum" 
        select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])"/>
<xsl:variable name="t" 
        select="sum($tracksInAlbum/integer[preceding-sibling::key[1]='Total Time']
            [not(../true[preceding-sibling::key[1]='Disabled'])])"/>
<xsl:call-template name="formatTime">
<xsl:with-param name="t" select="$t"/>
</xsl:call-template>
</xsl:template>


<xsl:template name="iTunesTimeAlbum">
<xsl:variable name="tracksInAlbum" 
        select="key('songsByAlbum',string[preceding-sibling::key[1]='Album'])"/>
<xsl:variable name="t" 
        select="sum($tracksInAlbum/integer[preceding-sibling::key[1]='Total Time'])"/>
<xsl:call-template name="formatTime">
<xsl:with-param name="t" select="$t"/>
</xsl:call-template>
</xsl:template>


<xsl:template name="iPodTimeTotal">
<xsl:variable name="t" select="sum(dict/integer[preceding-sibling::key[1]='Total Time']
        [not(../true[preceding-sibling::key[1]='Disabled'])])"/>
<xsl:call-template name="formatTime">
<xsl:with-param name="t" select="$t"/>
</xsl:call-template>
</xsl:template>


<xsl:template name="iTunesTimeTotal">
<xsl:variable name="t" select="sum(dict/integer[preceding-sibling::key[1]='Total Time'])"/>
<xsl:call-template name="formatTime">
<xsl:with-param name="t" select="$t"/>
</xsl:call-template>
</xsl:template>


<xsl:template name="iPodSizeTotal">
<xsl:variable name="s" select="sum(dict/integer[preceding-sibling::key[1]='Size']
        [not(../true[preceding-sibling::key[1]='Disabled'])])"/>
<xsl:value-of select="floor($s div (1000000)) div 1000"/>GB
</xsl:template>


<xsl:template name="iTunesSizeTotal">
<xsl:variable name="s" select="sum(dict/integer[preceding-sibling::key[1]='Size'])"/>
<xsl:value-of select="floor($s div (1000000)) div 1000"/>GB
</xsl:template>


<xsl:template name="formatTime">
<xsl:param name="t"/>
<xsl:if test="$t != 0">
<xsl:variable name="h" select="floor(($t div (1000*60*60)))"/>
<xsl:variable name="m" select="floor(($t div (1000*60)) mod 60)"/>
<xsl:variable name="s" select="floor(($t div 1000) mod 60)"/>
<xsl:if test="$h != 0"><xsl:value-of select="$h"/>:</xsl:if>
<xsl:value-of select="format-number($m,'00')"/>:<xsl:value-of select="format-number($s,'00')"/>
</xsl:if>
</xsl:template>

source: http://www.movable-type.co.uk/scripts/itunes-albumlist.html