XSLT: iterating over variable array to get sorted result not working.

≯℡__Kan透↙ 提交于 2019-12-23 04:45:48

问题


I am parsing itunes library xml file. The information in it is stored in following manner. Tracks information are stored separately and playlist information are stored differently. A playlist consists of different tracks.

A typical itunes playlist looks like below.

  <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
   <dict>
         <dict>
               <dict>
                  <key>Track ID</key>
                  <integer>1769</integer>
                  <key>Name</key>
                  <string>song_1</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/track1769.mp3</string>
                </dict>
               <dict>
                  <key>Track ID</key>
                  <integer>2413</integer>
                  <key>Name</key>
                  <string>song_2</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/track2413.mp3</string>
                </dict>

           </dict>

    <array>
        <dict>
            <key>Name</key><string>Library</string>
            <key>Playlist ID</key><integer>4053</integer>
            <array>
                <dict>
                    <key>Track ID</key><integer>2413</integer>
                </dict>
                <dict>
                    <key>Track ID</key><integer>1769</integer>
                </dict>
            </array>
        </dict>
        <dict>
            <key>Name</key><string>Movies</string>
            <key>Playlist ID</key><integer>6536</integer>
        </dict>
        <dict>
            <key>Name</key><string>TV Shows</string>
            <key>Playlist ID</key><integer>6539</integer>
        </dict>
        <dict>
            <key>Name</key><string>iTunes U</string>
            <key>Playlist ID</key><integer>5331</integer>
        </dict>
        <dict>
            <key>Name</key><string>Books</string>
            <key>Playlist ID</key><integer>6542</integer>
        </dict>
        <dict>
            <key>Name</key><string>Genius</string>
            <key>Playlist ID</key><integer>6551</integer>
        </dict>
        <dict>
            <key>Name</key><string>On-The-Go 1</string>
            <key>Playlist ID</key><integer>6568</integer>
            <array>
                <dict>
                    <key>Track ID</key><integer>2877</integer>
                </dict>
                <dict>
                    <key>Track ID</key><integer>2345</integer>
                </dict>
            </array>
        </dict>
    </array>
  </dict>
</plist>

Now I have written XSL stylesheet to get detail information of all tracks of given playlists. But the problem is, Under playlists tracks can be in random order and under track informations Ids are stored in sorted manner. When I use Xpath expressions I don't get informations in the same order as mentioned in playlists.

Here's my XSL.

<?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:variable name="tracks" select="/plist/dict/dict/dict[integer[preceding-sibling::key[1]='Track ID']=$playlist_tracks]" />

<xsl:for-each select="$playlist_tracks">
  <xsl:variable select="." name="current" />
    <xsl:for-each select ="$tracks[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>

But wit above XSLT I see only first element of the playlists. Can anybody point out whats the mistake? Any XSLT experts please enlighten me.

With the above XML the output dumps like below: <Track ID>,<Track Name>,<duration>,<location>

As we can see, in <plist><dict><dict><dict>, All track information are stored sorted by Track Ids. But Playlists contains tracks which are not sorted. so when I query for track infos into <plist><dict><dict><dict> from the track ids which I got from playlists plist/dict/array/dict/array/dict, I get sorted information. I want it in the same order as mentioned in playlist.

currently I get only first value. output: 2413,song_2,358870,/Users/rakesh/Music/iTunes/iTunes%20Media/Music/track2413.mp3

expected: 2413,song_2,358870,/Users/rakesh/Music/iTunes/iTunes%20Media/Music/track2413.mp3 1769,song_1,358870,/Users/rakesh/Music/iTunes/iTunes%20Media/Music/track1769.mp3


回答1:


This appears to be a problem with qt not liking the iterating of nested variables, here is a reworked version

<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> 


来源:https://stackoverflow.com/questions/7146775/xslt-iterating-over-variable-array-to-get-sorted-result-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!