Creating an XML Document in WSH

An eXtensible Markup Language (XML) file is a simple text-based database system that has been gaining a lot of popularity. Records are stored in a plain text format using a series of custom tags to separate pieces of data. Originally designed for portability and compatibility, these files are becoming commonplace for software engineers and web developers.

Today, I’m going to show you how to create XML files from within your WSH scripts. There are literally endless types of XML files out there. Among other things, they are often used for program configuration files, RSS feeds, web sites, and media playlists.

I’ve chosen to create an XSPF (pronounced “spiff”) playlist. XSPF stands for XML Shareable Playlist Format, an open source play list format designed for its simplicity and portability. The XSPF specification is gaining popularity and is already supported by a number of different media players.  You can see an example playlist below.

<?xml version="1.0" encoding="UTF-8"?>

<playlist version="1" xmlns="http://xspf.org/ns/0/">

   <trackList>

       <track>

          <location>file:///URI/to/file.mp3</location>

          <title>Song Title</title>

          <creator>Artist or Band</creator>

          <info>http://link/to/additional/information</info>

          <album>Album Title</album>

          <trackNum>0</trackNum>

       </track>

       <track>

          <location>file:///URI/to/file.mp3</location>

          <title>Song Title</title>

          <creator>Artist or Band</creator>

          <info>http://link/to/additional/information</info>

          <album>Album Title</album>

          <trackNum>0</trackNum>

       </track>

   </trackList>

</playlist>

This is a very basic example of an XSPF playlist—just the bare necessities. A “playlist” element houses a track listing that is made up of multiple “track” elements. I won’t go into too much detail about the specification itself. It’s very simple to figure out, but you can find out more about XSPF by visiting the project home page.

Are you ready to get your hands dirty and get down to code? I thought you might be.

{mospagebreak title=Microsoft’s XML Parser}

XML files use an interpreter known as a parser. Every modern browser has one, and Windows ships one natively as a part of Internet Explorer. The Microsoft XML Parser includes a scripting interface that allows us to easily read and create XML files.

I know what you’re thinking. “You said that XML files were just text files. Why not just use the FileSystemObject?”

The truth is that you could use the FileSystemObject. However, attempting to parse out elements and their attributes could prove to be a tedious task, considering there’s already a tool available to do the job.

Set objParser = CreateObject("Microsoft.XMLDOM")

With that being said, our script must first connect to the Microsoft XML Parser object. This line of code creates a new blank XML Document object. We can then load an existing XML file into that document or, as in our case, we can begin constructing a new one by building an element tree.

Set objPlaylist = objParser.createElement("playlist")

objParser.appendChild objPlaylist

 

We’re going to begin by creating our root element “playlist.” The XML Document object provides the createElement method. Note that this only creates the element in memory. It doesn’t actually attach it to the document. To do that, we’ll need to use the appendChild method.

The appendChild method will attach our new element to the document tree.  Since we are calling appendChild from the document object itself, our new element is attached as a child of the document object, making a new root level element within the document.

<playlist version="1" xmlns="http://xspf.org/ns/0/">

If you look back at our example, you will see that the playlist element has two attributes associated with it. One is associated with the version number of the XSPF specification that we are using, and the other binds to the XSPF namespace.

objPlaylist.setAttribute "version", "1"

objPlaylist.setAttribute "xmlns", "http://xspf.org/ns/0/"

We can add these attributes to the playlist element using the setAttribute method provided by its object reference. The method accepts two parameters; the first is a text string that indicates the attribute name and the second is a text string indicating its value.

Set objTrackList = objParser.createElement("trackList")

objPlaylist.appendChild objTrackList

We continue building our document by creating the next element. The trackList element is a child of the playlist element. So again, we will use the XML Document object’s createElement method to create an element reference. This time, however, we want this element to be a child of the playlist element so we will be calling the appendChild method from the playlist method rather than from the document object as before.

This element should be named “trackList” exactly. The capitalized letter is part of the XSPF specification.

At this point, our XML document should look something like this:

<playlist version="1" xmlns="http://xspf.org/ns/0/">

   <trackList>

Note that if you open the document in a text editor at any point throughout this article, you may not see it as nicely formatted as I’m showing you here. Your document may appear as one long single line of text. This is not a problem. Your XML file will work just as well either way. I’m only formatting my examples for readability purposes.

{mospagebreak title=Building the document tree}

To continue building the document tree, we will continue adding elements and attaching them to their parent elements.

Set objTrack = objParser.createElement("track")

objTrackList.appendChild objTrack

This bit of code creates a “track” element and adds it as a child of the trackList element. Now we can build references to our audio tracks in our playlist. Each track element represents one track and has several child elements that provide properties about that track.

Set objLocation = objParser.createElement("location")

objLocation.Text = "file:///URI/to/mp3/file.mp3"

objTrack.appendChild objLocation

The first element we will create is the location element. The location element is used to provide a URI to the location of the audio track. This is added in the same way as every other element to this point. Notice, however, that I’ve added an extra step here. The Text property is used to set the value of element. In other words, it provides the text that is found between the opening and closing location tags.

Set objTitle = objParser.createElement("title")

objTitle.Text = "Song Title"

objTrack.appendChild objTitle

Next, we will add a title element. This is used to provide the title of the audio track. This code is identical to the code we used to create the location element in the last step. Notice that both of them are using the appendChild method of the track element. This makes them both children of that element and, in turn, siblings to each other.

<playlist version="1" xmlns="http://xspf.org/ns/0/">

   <trackList>

       <track>

          <location>file:///URI/to/file.mp3</location>

          <title>Song Title</title>

       </track>

   </trackList>

</playlist>

A look at our file now would reveal something like the example above. Notice how the location and title elements appear at the same level as children of the track element.

Set objCreator = objParser.createElement("creator")

objCreator.Text = "Artist or Band"

objTrack.appendChild objCreator

 

Set objInfo = objParser.createElement("info")

objInfo.Text = "http://URI/to/resource/info.html"

objTrack.appendChild objInfo

 

Set objAlbum = objParser.createElement("album")

objAlbum.Text = "Album Title"

objTrack.appendChild objAlbum

 

Set objTrackNum = objParser.createElement("trackNum")

objTrackNum.Text = "0"

objTrack.appendChild objTrackNum

We continue adding each of the other property elements for the audio track:  creator provides an artist or band name associated with the track, info provides a URL to more information about the track (such as where it can be purchased), album provides the track’s album title, and trackNum is used to indicate the track number on the album.

You can now repeat the code for creating the track element and each of its children for every track that you wish to add to your playlist.

Set objIntro = objParser.createProcessingInstruction( _

   "xml","version=’1.0′ encoding=’UTF-8’")

objParser.insertBefore objIntro, objParser.childNodes(0)

Finally, we need to add the very first line that defines this as an XML file. This is known as a processing instruction. The XML Document object provides the createProcessingInstruction method for this. It accepts two parameters. The first parameter indicates the type of processing instruction to be used and the second provides any additional parameters.

<?xml version="1.0" encoding="UTF-8"?>

Look at the line that I’m using to add this instruction. The childNodes property returns a collection of childNodes for an object, in this case, the document itself.  By specifying item 0 I am referring to the first element in that collection, or its first child element. Then I’m using the XML Document object’s insertBefore method. It accepts two parameters and inserts the object in the first parameter before the object in the second parameter. So this line inserts objIntro before the first element in our XML document, effectively making sure it always appears as the first line of the document.

objParser.Save "C:Playlist.xml"

At this point, the XML document resides only in memory. You can write it to a file using the XML Document object’s Save method.

{mospagebreak title=Extending the concept}

At this point you’ve learned how to create an XML document from within WSH.  However, you still need to manually add each element. Chances are, you are looking for a way to automate the entire process.

We’re going to build a script that will create an XSPF playlist for all of the MP3 files found in your My Music folder.

Set objParser = CreateObject("Microsoft.XMLDOM")

 

WScript.Echo "Building XSPF Playlist…"

 

Set objPlaylist = objParser.createElement("playlist")

objParser.appendChild objPlaylist

objPlaylist.setAttribute "version", "1"

objPlaylist.setAttribute "xmlns", "http://xspf.org/ns/0/"

 

Set objTrackList = objParser.createElement("trackList")

objPlaylist.appendChild objTrackList

The script begins, as you might imagine, by creating the beginnings of an XML document. We’re simply connecting to the XML Document object and beginning to build the document tree, as you’ve already seen.

<playlist version="1" xmlns="http://xspf.org/ns/0/">

   <trackList>

At this point, our XML file is pretty basic. Now we’re ready to begin adding the track information for each of our MP3 files.

Set objShell = CreateObject("Shell.Application")

Set objFolder = objShell.NameSpace(&Hd&)

Set colFiles = objFolder.Items

To do so, I’ve used the Shell Application object’s NameSpace method to return a ShellFolder object for the My Music folder. The “&Hd&” is a shell folder constant that represents the My Music folder for the currently logged-on user. I’m then using the ShellFolder object’s Items property to return a collection of all the files in that folder.

For Each objFile In colFiles

   strType = objFolder.GetDetailsOf(objFile, 2)

   If strType = "MP3 Format Sound" Then

 

       WScript.Echo "Adding", objFile.Name & ".mp3"

 

       Set objTrack = objParser.createElement("track")

       objTrackList.appendChild objTrack

         

       Set objLocation = objParser.createElement("location")

       objLocation.Text = objFile.Path

       objTrack.appendChild objLocation

         

       Set objTitle = objParser.createElement("title")

       objTitle.Text = objFolder.GetDetailsOf(objFile, 10)

       objTrack.appendChild objTitle

         

       Set objCreator = objParser.createElement("creator")

       objCreator.Text = objFolder.GetDetailsOf(objFile, 16)

       objTrack.appendChild objCreator

         

       Set objAlbum = objParser.createElement("album")

       objAlbum.Text = objFolder.GetDetailsOf(objFile, 17)

       objTrack.appendChild objAlbum

         

       Set objTrackNum = objParser.createElement("trackNum")

       objTrackNum.Text = objFolder.GetDetailsOf(objFile, 19)

       objTrack.appendChild objTrackNum

   End If

Next

Now it’s a simple matter of looping through each of the files in the colFiles collection. I’m making healthy use of the Shell Application object’s GetDetailsOf method. This method reads a file’s details, including ID3 tag information. I’m first using it to filter out only MP3 files. Then I’m using it to return the information to be used as the text part of the XML track elements.

Note that this script is designed to run on Windows XP. For Vista, you will need to change the integer parameter being used. For more information, read my article titled Reading MP3 ID3 tags in WSH.

Set objIntro = objParser.createProcessingInstruction( _

   "xml","version=’1.0′ encoding=’UTF-8’")

objParser.insertBefore objIntro,objParser.childNodes(0)

 

objParser.Save "C:Playlist.xml"

 

WScript.Echo "…Building Complete"

Finally, the script is completed by adding the processing instruction and saving the file.

That’s all there is to it. The Microsoft XML Parser makes it very easy and efficient to create XML files. It also provides several methods for reading and updating XML files as well, but I’ll save those for future articles. Until next time, keep coding!

[gp-comments width="770" linklove="off" ]