0

I'm looking to parse some data from the iTunes Library XML file and for that I'd like to have an elegant solution in VBScript to parse the key/value pairs. This is the XML structure:

<plist version="1.0">
    <dict>
        <dict>
            <key>1</key>
            <dict>
                <key>Location</key><string>"file1.mp3"</string>
            </dict>
            <key>2</key>
            <dict>
                <key>Location</key><string>"file2.mp3"</string>
            </dict>
        </dict>
    </dict>
</plist>

I've now listed only two key/value (<key>/<dict>) pairs but of course there are many.

I'd like to parse this into some kind of dictionary object like so:

1 file1.mp3
2 file2.mp3

I can think of some ways to achieve this, like involving the NextSibling() method, but that really seems too far-fetched to me.

So what would be a more official/elegant solution to this problem? Thanks in advance!

Daan
  • 1,417
  • 5
  • 25
  • 40

1 Answers1

0

I would search for the locations and then use family relations to get the key and the file. In code:

  Dim oFS      : Set oFS      = CreateObject("Scripting.FileSystemObject")
  Dim sFSpec   : sFSpec       = goFS.GetAbsolutePathName("..\testdata\xml\so23425116.xml")
  Dim objMSXML : Set objMSXML = CreateObject("Msxml2.DOMDocument")
  objMSXML.setProperty "SelectionLanguage", "XPath"
  objMSXML.async = False
  objMSXML.load sFSpec

  If 0 = objMSXML.parseError Then
     Dim sXPath : sXPath     = "/plist/dict/dict/dict/key[. = ""Location""]"
     Dim ndlFnd : Set ndlFnd = objMSXML.selectNodes(sXPath)
     If 0 = ndlFnd.length Then
        WScript.Echo sXPath, "not found"
     Else
        Dim dicKV : Set dicKV = CreateObject("Scripting.Dictionary")
        Dim ndFnd, ndLoc, ndKey
        For Each ndFnd In ndlFnd
            Set ndLoc = ndFnd.nextSibling
            Set ndKey = ndFnd.parentNode.previousSibling
            WScript.Echo ndKey.text, ndLoc.text
            dicKV(ndKey.text) = ndLoc.text
        Next
        WScript.Echo "------------"
        Dim sKey
        For Each sKey In dicKV
            WScript.Echo sKey, dicKV(sKey)
        Next
     End If
  Else
     WScript.Echo objMSXML.parseError.reason
  End If

sample output (for a variant of your sample .xml):

1 "file1.mp3"
2 "file2.mp3"
290 file://localhost/D:/iTunes/Bob%20Russell%20Sermons/Sermons/1999/01-03%20Good%20News.mp3
------------
1 "file1.mp3"
2 "file2.mp3"
290 file://localhost/D:/iTunes/Bob%20Russell%20Sermons/Sermons/1999/01-03%20Good%20News.mp3

Disclaimers:

  • I don't use iTunes, so I'm not sure that the 2 randomly selected sample .xml I used for testing are really representative.
  • The file specs obviously need some cleaning
Ekkehard.Horner
  • 38,498
  • 2
  • 45
  • 96
  • Thank you very much for your clear code! Well, at least I was looking in the right direction with `nextSibling()`... There's still a problem though: in the iTunes XML file, characters like a space are encoded differently, as you can see from your own output. I need to end up with the normal characters: `[`, `–` etc. Is there any solution for this, besides manually replacing the characters? – Daan May 02 '14 at 14:56
  • Alright, I found this great solution and used the 3rd method: http://stackoverflow.com/questions/17880395/decoding-url-encoded-utf-8-strings-in-vbscript. All seems to work well. :) Tell me what you think. – Daan May 02 '14 at 15:29