Sort XML Playlist

S

scott

I use Windows Media Player (WMP) version 9 and have a great deal of WMP
playlists. One short coming of WMP is that there is no way to sort
playlists. However, WMP's playlists look like there are in XML format (See
Sample Code below).

I'm a VB/ASP/Access developer, but only have a basic understanding of XML
files. I was curious if it would be possible to sort a XML playlist like my
sample playlist below?


SAMPLE CODE: ***********************

<?wpl version="1.0"?>
<smil>
<head>
<meta name="Generator" content="Microsoft Windows Media Player --
9.0.0.3250"/>
<author/>
<title>Sample WMP Playlist</title>
</head>
<body>
<seq>
<media src="D:\mp3\The Doors\The Doors_L.A. Woman_L.A.
Woman_05.mp3" cid="{CBD4C35E-4691-49AE-8194-FE354E48F621}"
tid="{29CC328D-F875-41A3-866D-C7303EB3E5C5}"/>
<media src="D:\mp3\The Doors\The Doors_The Doors_Break on
Through_01.mp3" tid="{61D292E7-A180-4D45-9578-67878763D914}"/>
<media src="D:\mp3\The Doors\The Doors_L.A. Woman_Love Her
Madly_02.mp3" cid="{1C8D07ED-F2CD-46C8-B785-38D33088764E}"
tid="{248770B2-BD01-4E59-BEF4-F24047B5F9B0}"/>
<media src="D:\mp3\The Doors\The Doors_Morrison Hotel_Roadhouse
Blues_01.mp3" cid="{7DB54FF5-2B9B-4ACA-8747-4B783C0CFFBF}"
tid="{7D4E2093-20FE-4317-8DFF-6BE6BBE57AFB}"/>
<media src="D:\mp3\The Doors\The Doors_Strange Days_Love Me Two
Times_03.mp3" cid="{E0272594-9590-4EBF-94C8-C7918C23B6F0}"
tid="{C06CF2E1-9094-4CF3-A7A0-CED6F8683F98}"/>
<media src="D:\mp3\The Doors\The Doors_The Doors_Back Door
Man_07.mp3" tid="{697A39F8-FBCE-4308-8424-E5E0754005DC}"/>
<media src="D:\mp3\Led Zeppelin\Box Set 1 (vol 1)\Led
Zeppelin_Led Zeppelin [Box Set] (Vol 1)_Traveling Riverside Blues_11.mp3"/>
<media src="D:\mp3\Led Zeppelin\Box Set 1 (vol 1)\Led
Zeppelin_Led Zeppelin [Box Set] (Vol 1)_Whole Lotta Love_01.mp3"/>
<media src="D:\mp3\Led Zeppelin\Box Set 1 (vol 2)\Led
Zeppelin_Led Zeppelin [Box Set] (Vol 2)_Immigrant Song_03.mp3"/>
<media src="D:\mp3\Led Zeppelin\Box Set 1 (vol 2)\Led
Zeppelin_Led Zeppelin [Box Set] (Vol 2)_Misty Mountain Hop_12.mp3"/>
<media src="D:\mp3\Led Zeppelin\Box Set 1 (vol 3)\Led
Zeppelin_Led Zeppelin [Box Set] (Vol 3)_Kashmir_01.mp3"
cid="{90507084-8561-47BA-8F42-61F9A02B6925}"
tid="{8F814FA3-7C8F-4ACB-AE3B-578691B9BE51}"/>
<media src="D:\mp3\The Doors\The Doors_Strange Days_Moonlight
Drive_06.mp3" tid="{B7BE8CBC-6D8E-47D0-9CDD-96D317C61C7D}"
cid="{CED8E89F-E95D-450F-ACEA-AA3DFC34E537}"/>
</seq>
</body>
</smil>
 
M

Martin Honnen

scott said:
I'm a VB/ASP/Access developer, but only have a basic understanding of XML
files. I was curious if it would be possible to sort a XML playlist like my
sample playlist below?

MSXML 3 (IE 6/7 come with MSXML 3) supports XSLT 1.0 transformations
which can transform XML to XML and sort with the xsl:sort instruction.
So that is a possible way to sort.
What exactly do you want to sort on however? Do you want to sort on the
src attribute of the media elements?
 
S

scott

From looking at the xml structure, it looks like sorting the src attribute
would be about the only thing that I could sort by. If I could sort that,
then at least the artists would be in order within the playlist.
 
A

Anthony Jones

scott said:
From looking at the xml structure, it looks like sorting the src attribute
would be about the only thing that I could sort by. If I could sort that,
then at least the artists would be in order within the playlist.


I'm not sure where ASP fits into all this however here is a VBScript that
will do the sort based on the src attribute:-

Dim oDOM
Dim oSeq
Dim arrMedia
Dim i

Set oDOM = CreateObject("MSXML2.DOMDocument.3.0")
oDOM.load "g:\temp\test.smil"

Set oSeq = oDOM.selectSingleNode("/smil/body/seq")

ReDim arrMedia(oSeq.childNodes.length - 1)

For i = 0 To UBound(arrMedia)
Set arrMedia(i) = oSeq.childNodes(i)
Next

ShellSortObj arrMedia, GetRef("Comparator")

For i = 0 To UBound(arrMedia)
oSeq.appendChild arrMedia(i)
Next

oDOM.save "g:\temp\test2.smil"

Function Comparator(roLeft, roRight)
Comparator = roLeft.getAttribute("src") > roRight.getAttribute("src")
End Function

Sub ShellSortObj(rarr, fnCompare)

Dim i, j
Dim distance
Dim tmpValue
Dim lCount

lCount = UBound(rarr) + 1

distance = 0
Do
distance = distance * 3 + 1
Loop Until distance > lCount

Do
distance = distance \ 3
For i = distance To lCount - 1
If fnCompare(rarr(i - distance), rarr(i)) Then
j = i
Set tmpValue = rarr(j)
Do
Set rarr(j) = rarr(j - distance)
j = j - distance
If j + 1 <= distance Then Exit Do
Loop While fnCompare(rarr(j - distance), tmpValue)
' move the data back in the array
Set rarr(j) = tmpValue
End If
Next
Loop Until distance <= 1

End Sub

Note the at its the comparator function that defines the basis for sort. So
with a few utlity functions:-

Function GetFolder(FilePath)

Dim lLastSlash

lLastSlash = InStrRev(FilePath, "\")

If lLastSlash > 0 Then
GetFolder = Left(FilePath, lLastSlash - 1)
End If

End Function

Function GetTrackNo(FileName)

Dim lLastSlash
Dim lLastDot
Dim sFileTitle

lLastSlash = InStrRev(FileName, "\")
lLastDot = InStrRev(FileName, ".")

sFileTitle = Mid(FileName, lLastSlash + 1, lLastDot - lLastSlash - 1)

GetTrackNo = CInt(Right(sFileTitle, 2))

End Function

We can change the comparator to:-

Function Comparator(roLeft, roRight)

Dim sLeftFolder
Dim sRightFolder
Dim sLeftTrackNo
Dim sRightTrackNo

sLeftFolder = GetFolder(roLeft.getAttribute("src"))
sRightFolder = GetFolder(roRight.getAttribute("src"))

If sLeftFolder = sRightFolder Then
sLeftTrackNo = GetTrackNo(roLeft.getAttribute("src"))
sRightTrackNo = GetTrackNo(roRight.getAttribute("src"))
Comparator = sLeftTrackNo > sRightTrackNo
Else
Comparator = sLeftFolder > sRightFolder
End If

End Function

Now it will sort by folder then by track number. Hence a sensible folder
structure which has a folder per artist in which there is a folder per album
will sort quite nicely.

You (or other readers) might be tempted to optimize the code (sort oriented
questions tends to bring that desire out of people) but don't in the real
world the performance of thsi code is perfectly adequate.
 
S

scott

I assume that "g:\temp\test.smil" should be my playlist path. What does the
path in the below line represent?

Set oSeq = oDOM.selectSingleNode("/smil/body/seq")
 
D

Daniel Crichton

scott wrote on Tue, 2 Oct 2007 11:20:56 -0500:
I assume that "g:\temp\test.smil" should be my playlist path. What does
the path in the below line represent?
Set oSeq = oDOM.selectSingleNode("/smil/body/seq")


The above line will set the object variable oSeq to point to the first node
that matches in the structure

<smil>
<body>
<seq>

the following line then loops through the childNodes (which will be all the
<media> nodes)

Dan




I'm not sure where ASP fits into all this however here is a VBScript
that will do the sort based on the src attribute:-
Dim oDOM
Dim oSeq
Dim arrMedia
Dim i
Set oDOM = CreateObject("MSXML2.DOMDocument.3.0")
oDOM.load "g:\temp\test.smil"
Set oSeq = oDOM.selectSingleNode("/smil/body/seq")
ReDim arrMedia(oSeq.childNodes.length - 1)
For i = 0 To UBound(arrMedia)
Set arrMedia(i) = oSeq.childNodes(i)
Next
ShellSortObj arrMedia, GetRef("Comparator")
For i = 0 To UBound(arrMedia)
oSeq.appendChild arrMedia(i)
Next
oDOM.save "g:\temp\test2.smil"
Function Comparator(roLeft, roRight)
Comparator = roLeft.getAttribute("src") > roRight.getAttribute("src")
End Function
Sub ShellSortObj(rarr, fnCompare)
Dim i, j
Dim distance
Dim tmpValue
Dim lCount
lCount = UBound(rarr) + 1
distance = 0
Do distance = distance * 3 + 1
Loop Until distance > lCount
Do distance = distance \ 3
For i = distance To lCount - 1
If fnCompare(rarr(i - distance), rarr(i)) Then j = i
Set tmpValue = rarr(j)
Do
Set rarr(j) = rarr(j - distance)
j = j - distance
If j + 1 <= distance Then Exit Do
Loop While fnCompare(rarr(j - distance), tmpValue)
' move the data back in the array
Set rarr(j) = tmpValue
End If
Next
Loop Until distance <= 1
End Sub
Note the at its the comparator function that defines the basis for
sort.
So with a few utlity functions:-
Function GetFolder(FilePath)
Dim lLastSlash
lLastSlash = InStrRev(FilePath, "\")
If lLastSlash > 0 Then
GetFolder = Left(FilePath, lLastSlash - 1)
End If
End Function
Function GetTrackNo(FileName)
Dim lLastSlash
Dim lLastDot
Dim sFileTitle
lLastSlash = InStrRev(FileName, "\")
lLastDot = InStrRev(FileName, ".")
sFileTitle = Mid(FileName, lLastSlash + 1, lLastDot - lLastSlash - 1)
GetTrackNo = CInt(Right(sFileTitle, 2))
End Function
We can change the comparator to:-
Function Comparator(roLeft, roRight)
Dim sLeftFolder
Dim sRightFolder
Dim sLeftTrackNo
Dim sRightTrackNo
sLeftFolder = GetFolder(roLeft.getAttribute("src"))
sRightFolder = GetFolder(roRight.getAttribute("src"))
If sLeftFolder = sRightFolder Then sLeftTrackNo =
GetTrackNo(roLeft.getAttribute("src"))
sRightTrackNo = GetTrackNo(roRight.getAttribute("src"))
Comparator = sLeftTrackNo > sRightTrackNo
Else
Comparator = sLeftFolder > sRightFolder
End If
End Function
Now it will sort by folder then by track number. Hence a sensible
folder structure which has a folder per artist in which there is a
folder per album will sort quite nicely.
You (or other readers) might be tempted to optimize the code (sort
oriented questions tends to bring that desire out of people) but
don't in the real world the performance of thsi code is perfectly
adequate.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,085
Messages
2,570,597
Members
47,219
Latest member
Geraldine7

Latest Threads

Top