XSLT 2.0: how to iterate over stored array values ​​inside a for-each loop with conditional validation?

I am writing an xsl stylesheet to extract information from an iTunes library. xml file.

I want to store information about the tracks of playlists in an array, and then iterate over them to get additional information. I am confused how to store values ​​in an array in xslt?

My attempt:

<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" /> <xsl:template match="/"> <xsl:variable name="tracks" select="plist/dict/array/dict[integer[preceding-sibling::key[1]='Playlist ID']=6711]/array/dict/integer[preceding-sibling::key[1]='Track ID']" /> <!-- I want to iterate over that array outside for-each loop and gather more information, The below code is not working.--> <xsl:for-each select="$tracks"> <xsl:value-of select="." /> <xsl:value-of select="plist/dict/dict/dict[integer[preceding-sibling::key[1]='Track ID']="."]/integer[preceding-sibling::key[1]='Track ID']" /> <xsl:value-of select="plist/dict/dict/dict[integer[preceding-sibling::key[1]='Track ID']="."]/string[preceding-sibling::key[1]='Name']" /> <xsl:value-of select="plist/dict/dict/dict[integer[preceding-sibling::key[1]='Track ID']="."]/string[preceding-sibling::key[1]='Total Time']" /> <xsl:value-of select="plist/dict/dict/dict[integer[preceding-sibling::key[1]='Track ID']="."]/string[preceding-sibling::key[1]='Location']" /> <xsl:text>&#xa;</xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet> 

Typical identifiers for tracks that are populated in the variable array "tracks" are presented below in the itunes list. I want to specify a name, location, time information for each track identifier stored in the array. Something is wrong with my conditions.

 <plist> <dict> <dict> <dict> <key>Track ID</key> <integer>1633</integer> <key>Name</key> <string>Right here</string> <key>Kind</key> <string>MPEG audio file</string> <key>Total Time</key> <integer>358870</integer> <key>Location</key> <string>/Users/rakesh/Music/iTunes/iTunes%20Media/Music/track1633.mp3</string> </dict> <dict> <!-- Next Track info --> </dict> </dict> </dict> </plist> 

I'm stuck here. Can any XSLT experts help me?

+4
source share
1 answer

You can simply create a variable and populate its results with an XPath expression in one go, rather than interacting to create it.

 <xsl:variable name="tracks" select="plist/dict/array/dict[integer[preceding-sibling::key[1]='Playlist ID']=6711]/array/dict/integer[preceding-sibling::key[1]='Track ID']" /> 

Alternatively, you could use xsl: keys at the beginning of your document, I assume that the path to the track information is /plist/dict/array/dict , with the first dict key << 22>

 <xsl:key name="playlists" match="plist/dict/array/dict/array/dict/integer[preceding-sibling::key[1]='Track ID']" use="../../../integer[preceding-sibling::key[1]='Playlist ID']" /> <xsl:key name="tracks" match="/plist/dict/array[preceding-sibling::key[1]='Tracks']/dict" use="integer[preceding-sibling::key[1]='Track ID']" /> 

This allows you to execute key('playlists','4555') to return all the tracks associated with the playlist ID 4555 , as well as key('tracks','1234') to get the dict object associated with track ID 1234

Then you can combine the two together to make

 <xsl:variable "mytracks" select="key('tracks',key('playlists','6711'))" /> 

This will set $mytracks to an array of dict objects for the tracks in playlist 6711. It also has the advantages of increasing the speed provided by xsl: key

EDIT UPDATE ----

I assume you are trying to create a CSV, so this code should do this

 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> <xsl:output method="text" /> <xsl:key name="playlists" match="plist/dict/array/dict/array/dict/integer[preceding-sibling::key[1]='Track ID']" use="../../../integer[preceding-sibling::key[1]='Playlist ID']" /> <xsl:key name="tracks" match="/plist/dict/dict/dict" use="integer[preceding-sibling::key[1]='Track ID']" /> <xsl:template match="/"> <xsl:variable name="myplaylist" select="'6711'"/> <xsl:for-each select="key('tracks',key('playlists',$myplaylist))"> <xsl:value-of select="integer[preceding-sibling::key[1]='Track ID']"/> <xsl:text>,</xsl:text> <xsl:value-of select="string[preceding-sibling::key[1]='Name']"/> <xsl:text>,</xsl:text> <xsl:value-of select="integer[preceding-sibling::key[1]='Total Time']"/> <xsl:text>,</xsl:text> <xsl:value-of select="string[preceding-sibling::key[1]='Location']"/> <xsl:text>&#xa;</xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet> 

to match a different playlist id just change the value of myplaylist

- EDIT version without xsl:key , again just change the value of the myplaylist variable

- EDIT Now mofolizes to the original playlist sort order --EDIT Attempt to circumvent Qt restrictions

  <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> <xsl:output method="text" /> <xsl:template match="/"> <xsl:variable name="myplaylist" select="'4053'"/> <xsl:variable name="playlist_tracks" select="/plist/dict/array/dict[integer[preceding-sibling::key[1]='Playlist ID']=$myplaylist]/array/dict/integer[preceding-sibling::key[1]='Track ID']" /> <xsl:for-each select="$playlist_tracks"> <xsl:variable select="." name="current" /> <xsl:for-each select ="/plist/dict/dict/dict[integer[preceding-sibling::key[1]='Track ID']=$current]" > <xsl:value-of select="integer[preceding-sibling::key[1]='Track ID']"/> <xsl:text>,</xsl:text> <xsl:value-of select="string[preceding-sibling::key[1]='Name']"/> <xsl:text>,</xsl:text> <xsl:value-of select="integer[preceding-sibling::key[1]='Total Time']"/> <xsl:text>,</xsl:text> <xsl:value-of select="string[preceding-sibling::key[1]='Location']"/> <xsl:text>&#xa;</xsl:text> </xsl:for-each> </xsl:for-each> </xsl:template> </xsl:stylesheet> 
+3
source

All Articles