BeaverBlogg

April 9, 2007

XML, XMLDom and ASP, Part 1

Filed under: ASP, Articles, XML — Karl @ 10:30 pm

Everyone who works with the web these days know what XML is, but how many know how to really use it? Over the past months I’ve seen lots of people using regexps to parse XML as text strings and people trying to use the XMLDom in ASP and failing miserably. They just look at me like I’m stupid or something when I try to mention XPath as the correct way to go and kindly explain that they use XML, not XPath. I’ve been working with XML and XMLDom for over a bit over a year now and I feel really comfortable with it. It can do just about everything I want it to.

Here is a quite typical XML document. It contains a root element, a description tag and a collection of files.

Thats the way I like to have my XML. As much as possible as attributes. Some people seem to prefer this type though:

This is easier to understand for a beginner maybe but it’s not as easy to work with as the first data.

Anyway, lets try to get some data out of this. Lets imagine that the XML data is avaible in a filed called Data.xml in the same folder as the script. I’ll concentrate on the first XML example to start with.

The output of this would look something like this:

Description: Files attached to subject 1
File: beaver.jpg (12432 bytes)
File: beaver2.jpg (53174 bytes)

File: beaverfarm.doc (162475 bytes)

Not to shabby if you ask me. Lets take a quick stroll through the code now.

This part kinda explains itself. Declare the variables we are going to use. Then create the XMLDom object. We expect the data to be in a file called Data.xml in the current folder so we use Server.Mappath to get the absolute path to it and then calls .load from the XMLDom to load the data.

Then to be sure that there was no problems with the loading we check that the parseError property of the XMLDom is 0. If it isn’t something is wrong with our XML data and we show an error and quit.

The second part might be a bit harder to understand. First, we check if xmlDom.documentElement is nothing. If it is we throw an error and end the execution of the script. The documentElement of a XML document is the root element. In our case, the <root> tag. Every XML document needs one and only one root element. It can be named anything however so <root> isn’t a mandatory name, I just like to use it. If xmlDom.documentElement is nothing then it’s most likely that Data.xml was just an empty file. The XMLDom could parse the data without problems since there wasn’t anything to parse so this is a good thing to look for.

Next we try to read out the description element by using a XPath query. The function used is called selectSingleNode() and will return one single node (just as it’s name says) from the specified XPath query. It is avaible on any node in the document and works with relative XPaths. My XPath query is very simple and states that I want the node called “description”. I call the procedure from the documentElement node so I don’t have to write “root/description” which is it’s real path. Calling xmlDom.selectSingleNode(”root/description”) would return the same result.

After selecting the node and puttings it’s reference in the oNode variable we make an if-statement to see if it returned an object. If oNode is nothing then there wasn’t any node called “description” at the specified place in the document. If it isn’t nothing, then we expect that we got the right now and print it out using it’s .text property.

Not much left now. Here we use another procedure called selectNodes(). Like selectSingleNode() this procedure is avaible on all nodes and uses an XPath query to specify which nodes that we want. The main difference is that selectNodes() returns a collection of nodes instead of a single one.

The XPath query this time specifies that we want all “file” nodes under “files”. Not to hard to understand this one either. We put the reference to the collection in the nodeCol variable.

Next we initiate a for-each loop to go through all the nodes in a simple manner. We write out some markup (HTML) to make it look good. First we create a <span> tag with a title attribute in which we put the file description. Every node has a function called getAttribute() which takes one parameter with the attribute name. It returns an empty string if the attribute was not found and if it exists it returns the value. We make sure to HTMLEncode the value since we might not know what text is in the attribute and we don’t want anything that breaks our markup do we?

We end the opening <span> tag and write out the filename. We also add a paranthesis with the filesize in bytes. All using the .getAttribute function. Then finallyl we close the <span> tag and add a linebreak before the next file.

This is the way I like it to be done. If I got to shape the XML it would be as much as possible in the attributes and as few element nodes as possible. But since I don’t get to chose XML in all cases I still get suck with the second XML example some times. Here is how the code to produce the same output would look using that source data.

Not much happened there until the last block. Now I have to use selectSingleNode() to get the subnodes (child nodes) and look at their text property to get the values out. This might not seem like a great problem but most people get tired of havings lots and lots of element nodes after some time.

XPath is a quite powerful query language. You can specify in quite detail what nodes you want. For example, if I only want files that are smaller then 100kb I could just change a bit in the script to this:

Adding [] after a node tells that I want to evalutate something. The @ before “size” denotes that I want to look at an attribute node. It’s quite easy to understand for most. If I would like to do this using the second example the query would look like this:

This has been a brief introduction to working with the XMLDom in ASP aswell as making some simple XPath queries. It is also my first serious blogg post ever written so I hope someone finds it interessting. It was written in one evening without testing any of the code. Next time I’ll dig a bit deeper into XPath and show how you can retrieve XML data from an external websource using XMLHTTP.

10 Comments »

  1. This is the exact information I am looking on the internet for quite a while and very helpful.

    Comment by betty sun — April 18, 2007 @ 1:22 am

  2. Excellent work!!!
    Very clear!!
    Thanks :)

    Comment by Pablo méndez — May 12, 2007 @ 10:53 pm

  3. For me it’s the first article I found on the web I’m looking for a long time… It is exact the thing I want to do. However, I still didn’t manage to make tings work…
    Nevertheless: thanks!

    Comment by Djeek — May 22, 2008 @ 12:57 am

  4. Dear Karl, maybe you can and want to help me! I don’t get my code working!
    I try to read the values start, end, total, prev and next from the root element ‘playlist’:

    test.xml

    http://www.jojo.org/record.mp3
    Another Beatles Christmas Record
    The Beatles
    The Beatles Christmas Album (US Mono LP - Apple)
    Pop/Rock

    My code:

    <%
    dim xmlDom, oNode, nodeCol
    set xmlDom = Server.CreateObject(”MSXML2.DOMDocument.4.0″)
    xmlDom.load(Server.Mappath(”test.xml”))

    if(xmlDom.parseError 0) then
    Response.Write(”Invalid XML loaded. ” & xmlDom.parseError.reason)
    Response.End
    end if

    if xmlDom.documentElement is nothing then
    Response.Write(”Invalid XML loaded. No root tag exists”)
    Response.End
    end if

    Set oNode = xmlDom.getElementsByTagName(”playlist”)
    If oNode is nothing then
    Response.Write(”Playlist = Nothing”)
    End if

    Response.Write(”Start: “)
    Response.Write(Server.HTMLEncode(oNode.getAttribute(”start”)))
    Response.Write(”")

    Response.Write(”End: “)
    Response.Write(Server.HTMLEncode(oNode.getAttribute(”end”)))
    Response.Write(”")

    Response.Write(”Total: “)
    Response.Write(Server.HTMLEncode(oNode.getAttribute(”total”)))
    Response.Write(”")

    %>

    I hope you can help me since there are few people who work with xml in this way!
    Regards,
    Djeek

    Comment by Djeek — May 22, 2008 @ 1:32 am

  5. Sorry for the XML-mess:
    <?xml version="1.0" encoding="UTF-8" ?>
    <playlist version="1" xmlns="http://xspf.org/ns/0/" start="0" end="9" total="2648"
    prev="None" next="10">
      <title />
      <trackList>
        <track>
          <location>http://www.jojo.org/record.mp3</location>

          <title>Another Beatles Christmas Record</title>

          <creator>The Beatles</creator>
          <album>The Beatles Christmas Album (US Mono LP -
    Apple)</album>
          <genre>Pop/Rock</genre>
          <composer />
        </track>
        ...

    Comment by Djeek — May 22, 2008 @ 1:49 am

  6. Hi Djeek,

    Your code look mostly fine except that you use getElementsByTagName() to get the “playlist” element. Looking at your xml I see that your “playlist” is the rootelement which means that it can be found in xmlDom.documentElement so if you replace Set oNode = xmlDom.getElementsByTagName(”playlist”) with Set oNode = xmlDom.documentElement it should work.

    / Karl

    Comment by Karl — May 22, 2008 @ 10:49 am

  7. And again: The Master has Right!
    Thanks, all works fine!
    I realise XML is getting more and moere important. I try to change my web-auto-update-info-text(ini) file for a XML file.
    As a newbie, can you advise me a good tutorial for working with xml(4) with vb6 and/or xml with asp?

    Comment by Djeek — May 23, 2008 @ 8:23 am

  8. I’m not a VB6 man myself (prefer Delphi or C#) but it should be close enough that you can use the vbscript from this example in vb6 aswell (since they both utilize the same component).

    Comment by Karl — May 23, 2008 @ 10:23 am

  9. Hi,

    I enjoyed your nice description. I have a problem, that is I dont know how I can add an attribute to my xml while I am working with asp. I know there is a function in Jscript, but what should we do with asp (not .net)
    Thanks a lot
    Vafa

    Comment by vafa — June 29, 2008 @ 3:58 pm

  10. Hi Vafa,

    Do you need to add an attribute to an already existing xmldocument that you have loaded into an xmldom? If so, then your code should look something like this:

    set oMyAttr = oMyDom.createAttribute(”MyAttributeName”)
    oMyAttr.nodeValue = “MyNodeValue”
    oMyNode.setAttributeNode oMyAttr

    / Karl

    Comment by Karl — June 29, 2008 @ 4:51 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress