Link to home
Create AccountLog in
Avatar of greddin
greddinFlag for United States of America

asked on

Help with traversing xml with Microsoft.XMLDOM (non xslt)

I would like to know how to traverse an xml file using the Microsoft.XMLDOM and ASP only and non-xslt.  I have ncluded a sample of my xml file below for you to see.  I also have my code that I have so far.

When the page loads I'd like to expand the current selected section. The current selected section is determined by a query string "id" variable.

 For example, here's a sample output for what the "Products" page menu would be. If the query string id=4. (Products).

Products
    TVs
    Stereos
    DVRs
    CD Players
Services
About Us

If the user clicks on the "Services" page then the menu's sample output would be (id = 12).

Products
Services
    Installation
    Repair
About Us

And if the user clicked on About Us the sample output would be (id = 15):

Products
Services
About Us
    Employment
    Contact Us

(Clicking Employment the output would be (id=16):

Products
Services
About Us
    Employment
        Upload Resume
        Job Openings
    Contact Us

I'm just trying to show that I would always be giving an id to the code so that it knows which section to be "selected".

======== XML File =======================
<?xml version="1.0" encoding="utf-8"?>
<site href="index.htm" id="2" label="Home" level="0">
  <section href="Products/index.htm" id="3" label="Products" level="1">
    <section href="TVs/index.html" id="4" label="TVs" level="2"/>
    <section href="Stereos/index.html" id="5" label="Stereos" level="2"/>
    <section href="DVRs/index.html" id="6" label="DVRs" level="2"/>
    <section href="CDPlayers/index.html" id="10" label="CD Players" level="2"/>
  </section>
  <section href="Services/index.htm" id="12" label="Services" level="1">
    <section href="Installation/index.htm" id="13" label="Installation" level="2"/>
    <section href="Repair/index.htm" id="14" label="Repair" level="2"/>
  </section>
  <section href="AboutUs/index.htm" id="15" label="About Us" level="1">
    <section href="Employment/index.htm" id="16" label="Employment" level="2">
      <section href="Resume/index.htm" id="17" label="Upload Resume" level="3"/>
      <section href="Jobs/index.htm" id="18" label="Job Openings" level="3"/>
    </section>
    <section href="ContactUs/index.htm" id="19" label="Contact Us" level="2"/>
  </section>
</site>

The problem with this code below is that is displays too much. It displays even the root node.
======= my code so far ===============================
<%
Dim xmlDoc
Set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")

sub loadXML()
    xmlDoc.async = false
    xmlDoc.load(xmlFile)

    xmlDoc.load("sitenavigation.xml")

    If xmlDoc.parseError.errorCode <> 0 Then
          Response.Write("There was an error loading the xml file!<br>")
    Else
        Response.Write("xml file loaded.<br>")
        set doc = xmlDoc.documentElement
        traverse(doc)
    End If
end sub

sub traverse(tree)
    if tree.hasChildNodes then
        Response.Write("<ul><li>")
        Response.Write("<b>" & tree.tagName & " : </b>")
        nodes = tree.childNodes.length
        For i = 0 To tree.childNodes.length - 1
            traverse(tree.childNodes(i))
        Next
        Response.Write("</li></ul>")
    else
        Response.Write(tree.text)
    end if
   
end sub

call loadXML()

%>

Thank you,
-Greg
Avatar of greddin
greddin
Flag of United States of America image

ASKER

I tried modifying the code below to use Xpath but I'm getting this error:

Error Type:
Microsoft VBScript runtime (0x800A01B6)
Object doesn't support this property or method: 'tree.hasChildNodes'
/xml3.asp, line 23


<%
Dim xmlDoc
Set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")

sub loadXML()
    xmlDoc.async = false
    xmlDoc.load("sitenavigation.xml")

    If xmlDoc.parseError.errorCode <> 0 Then
          Response.Write("There was an error loading the xml file!<br>")
    Else
        Response.Write("xml file loaded.<br>")
        'set doc = xmlDoc.documentElement
        Set xmlNode = xmlDoc.selectNodes("//section[@id='3']/section")
        'traverse(doc)
        traverse(xmlNode)
        TotalNodes = cint(xmlNode.length)
        Response.Write "TotalNodes = " & TotalNodes & "<br><br>"
    End If
end sub

sub traverse(tree)
    if tree.hasChildNodes then
        Response.Write("<ul><li>")
        Response.Write("<b>" & tree.tagName & " : </b>")
        nodes = tree.childNodes.length
        For i = 0 To tree.childNodes.length - 1
            traverse(tree.childNodes(i))
        Next
        Response.Write("</li></ul>")
    else
        Response.Write(tree.text)
    end if
   
end sub

call loadXML()

%>
Avatar of jkmyoung
jkmyoung

The reason you're getting that error is because xmlDoc.selectNodes returns a XMLNodeList, not an XMLNode.

I see a couple ways of doing this:
1. You could stick with your original main code, but changing the traverse function to ignore the root node.
sub traverse(tree)
    if tree.name != "site"  then
        Response.Write("<ul><li>")
        Response.Write("<b>" & tree.tagName & " : </b>")
   end if

2. Use your new code, and change the subfunction to accept a nodelist with id param

        Set xmlNodes = xmlDoc.selectNodes("//site/section")
        traverse(xmlNodes)

sub traverse(tree, id)
For i = 0 to tree.Count -1
  Set xmlNode = tree.item[i]
  Set xpath = "//section[@id = "+id+"]"
  if (xmlNode.parentNode.Name = "site" || xmlNode.selectNodes(xpath)) // check if valid
        Response.Write("<ul><li>")
        Response.Write("<b>" & tree.tagName & " : </b>")
        nodes = tree.childNodes.length
        For i = 0 To tree.childNodes.length - 1
            traverse(tree.childNodes(i))
        Next
        Response.Write("</li></ul>")
    else
        Response.Write(tree.text)
    end if  
end sub

Hope you can work out what you need from this.
Avatar of greddin

ASKER

Ok, based on the second option you gave me, I have modifed the code to this:

<%
Dim xmlDoc
Set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")

sub loadXML()
    xmlDoc.async = false
    xmlDoc.load("C:\stellent\idcm1\weblayout\websites\CNIC_HQ_Site\sitenavigation.xml")

    nodeId = Request.QueryString("nodeId")

    If xmlDoc.parseError.errorCode <> 0 Then
          Response.Write("There was an error loading the xml file!<br>")
    Else
        Response.Write("xml file loaded.<br>")
        'set doc = xmlDoc.documentElement
        'Set xmlNode = xmlDoc.selectNodes("//section[@id='65']/section")
        Set xmlNodes = xmlDoc.selectNodes("//site/section")
        traverse(xmlNodes, nodeId)
     
        'traverse(doc)
        'traverse(xmlNode)
        TotalNodes = cint(xmlNode.length)
        Response.Write "TotalNodes = " & TotalNodes & "<br><br>"
    End If
end sub

sub traverse(tree, id)
    For i = 0 to tree.Count -1
        Set xmlNode = tree.item[i]
        Set xpath = "//section[@id = "+id+"]"
          if (xmlNode.parentNode.Name = "site" || xmlNode.selectNodes(xpath))
                Response.Write("<ul><li>")
                Response.Write("<b>" & tree.tagName & " : </b>")
                nodes = tree.childNodes.length
                For i = 0 To tree.childNodes.length - 1
                    traverse(tree.childNodes(i))
                Next
                Response.Write("</li></ul>")
            else
                Response.Write(tree.text)
            end if  
    Next
end sub

call loadXML()
%>

But I'm getting this error:

Error Type:
Microsoft VBScript compilation (0x800A0414)
Cannot use parentheses when calling a Sub
/xml5.asp, line 18, column 26
traverse(xmlNodes, nodeId)
-------------------------^

Any ideas?
Ah that's exclusively a VBScript error, didn't realize you weren't using VB.NET.
http://blogs.msdn.com/ericlippert/archive/2003/09/15/52996.aspx

Since there is no return value, call it like this:
        traverse xmlNodes, nodeId

Also nodeCount will not work the same way using this method.

I also realized           if (xmlNode.parentNode.Name = "site" || xmlNode.selectNodes(xpath))
should actually be          if (xmlNode.parentNode.Name = "site" || xmlNode.selectNodes(xpath) != null)
as this is not xslt.
Avatar of greddin

ASKER

Ok calling the traverse without the parenthesis seemed to get past that error.
Now I have this error:

Error Type:
Microsoft VBScript compilation (0x800A0401)
Expected end of statement
/xml5.asp, line 29, column 23
Set xmlNode = tree.item[i]
----------------------^

Thanks for your help.
Set xmlNode = tree.item(i);

does that work?
Avatar of greddin

ASKER

Yes, it's getting there. I'm just having some syntax errors converting the Javascript to Vbscript.

I'm getting this on the for loop. Can you help me convert this?

Error Type:
Microsoft VBScript compilation (0x800A0410)
Invalid 'for' loop control variable
/xml5.asp, line 35, column 6
For i = 0 To tree.childNodes.length - 1
-----^


Here's my current file:

<%
Dim xmlDoc
Set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")

sub loadXML()
    xmlDoc.async = false
    xmlDoc.load("C:\stellent\idcm1\weblayout\websites\CNIC_HQ_Site\sitenavigation.xml")

    nodeId = Request.QueryString("nodeId")

    If xmlDoc.parseError.errorCode <> 0 Then
          Response.Write("There was an error loading the xml file!<br>")
    Else
        Response.Write("xml file loaded.<br>")
        'set doc = xmlDoc.documentElement
        'Set xmlNode = xmlDoc.selectNodes("//section[@id='65']/section")
        Set xmlNodes = xmlDoc.selectNodes("//site/section")
        traverse xmlNodes, nodeId
     
        'traverse(doc)
        'traverse(xmlNode)
        TotalNodes = cint(xmlNode.length)
        Response.Write "TotalNodes = " & TotalNodes & "<br><br>"
    End If
end sub

sub traverse(tree, id)
    For i = 0 to tree.Count -1
        Set xmlNode = tree.item(i)
        Set xpath = "//section[@id = "+id+"]"
          if (xmlNode.parentNode.Name = "site") or (xmlNode.selectNodes(xpath) <> null) then
                Response.Write("<ul><li>")
                Response.Write("<b>" & tree.tagName & " : </b>")
                nodes = tree.childNodes.length
                For i = 0 To tree.childNodes.length - 1
                    traverse(tree.childNodes(i))
                Next
                Response.Write("</li></ul>")
            else
                Response.Write(tree.text)
            end if  
    Next
end sub


call loadXML()
%>
You already have an i in a previous loop

For j = 0 To tree.childNodes.length - 1
    traverse(tree.childNodes(j))
Next
Avatar of greddin

ASKER

Ah yes. I see that now. Now... I'm getting this error:
(File is below) Thanks for your help!

Error Type:
Microsoft VBScript runtime (0x800A01B6)
Object doesn't support this property or method: 'tree.Count'
/xml5.asp, line 28




Dim xmlDoc
Set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")

sub loadXML()
    xmlDoc.async = false
    xmlDoc.load("C:\stellent\idcm1\weblayout\websites\CNIC_HQ_Site\sitenavigation.xml")

    nodeId = Request.QueryString("nodeId")

    If xmlDoc.parseError.errorCode <> 0 Then
          Response.Write("There was an error loading the xml file!<br>")
    Else
        Response.Write("xml file loaded.<br>")
        'set doc = xmlDoc.documentElement
        'Set xmlNode = xmlDoc.selectNodes("//section[@id='65']/section")
        Set xmlNodes = xmlDoc.selectNodes("//site/section")
        traverse xmlNodes, nodeId
     
        'traverse(doc)
        'traverse(xmlNode)
        TotalNodes = cint(xmlNode.length)
        Response.Write "TotalNodes = " & TotalNodes & "<br><br>"
    End If
end sub

sub traverse(tree, id)
    For i = 0 to tree.Count -1
        Set xmlNode = tree.item(i)
        Set xpath = "//section[@id = "+id+"]"
          if (xmlNode.parentNode.Name = "site") or (xmlNode.selectNodes(xpath) <> null) then
                Response.Write("<ul><li>")
                Response.Write("<b>" & tree.tagName & " : </b>")
                nodes = tree.childNodes.length
                For x = 0 To tree.childNodes.length - 1
                    traverse(tree.childNodes(x))
                Next
                Response.Write("</li></ul>")
            else
                Response.Write(tree.text)
            end if  
    Next
end sub


call loadXML()
Avatar of greddin

ASKER

Ok. Current error is:

Microsoft VBScript runtime (0x800A01B6)
Object doesn't support this property or method: 'xmlNode.parentNode.Name'
/xml5.asp, line 33


<%
Dim xmlDoc
Set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")

sub loadXML()
    xmlDoc.async = false
    xmlDoc.load("C:\stellent\idcm1\weblayout\websites\CNIC_HQ_Site\sitenavigation.xml")

    nodeId = Request.QueryString("nodeId")

    If xmlDoc.parseError.errorCode <> 0 Then
          Response.Write("There was an error loading the xml file!<br>")
    Else
        Response.Write("xml file loaded.<br>")
        'set doc = xmlDoc.documentElement
        'Set xmlNode = xmlDoc.selectNodes("//section[@id='65']/section")
        Set xmlNodes = xmlDoc.selectNodes("//site/section")
        traverse xmlNodes, nodeId
     
        'traverse(doc)
        'traverse(xmlNode)
        TotalNodes = cint(xmlNode.length)
        Response.Write "TotalNodes = " & TotalNodes & "<br><br>"
    End If
end sub

sub traverse(tree, id)
    'For i = 0 to tree.Count -1
    For i = 0 to tree.length-1
        Set xmlNode = tree.item(i)
        xpath = "//section[@id='" & id & "']"
          if (xmlNode.parentNode.Name = "site") or (xmlNode.selectNodes(xpath) <> null) then
                Response.Write("<ul><li>")
                Response.Write("<b>" & tree.tagName & " : </b>")
                nodes = tree.childNodes.length
                For x = 0 To tree.childNodes.length-1
                    traverse(tree.childNodes(x))
                Next
                Response.Write("</li></ul>")
            else
                Response.Write(tree.text)
            end if  
    Next
end sub


call loadXML()
ASKER CERTIFIED SOLUTION
Avatar of jkmyoung
jkmyoung

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account