0

I am trying to Select nodes from some webservice response XML to no avail. For some reason I am able to select the root node ("xmldata") however, when I try to drill deeper("xmldata/customers") everything is returned empty! Below is the a sample of the XML that is returned by the webservice.

<xmldata>
  <customers>
    <customerid>22506</customerid>
    <firstname>Jim</firstname>
    <issuperadmin>N</issuperadmin>   
    <lastname>Jones</lastname>
  </customers>
</xmldata>

and here is the code I am trying to select customerid, firstname, and lastname;

' Send the Xml
oXMLHttp.send Xml_to_Send

' Validate the Xml
dim xmlDoc
set xmlDoc = Server.CreateObject("Msxml2.DOMDocument")
xmlDoc.load (oXMLHttp.ResponseXML.text)
if(len(xmlDoc.text) = 0) then
    Xml_Returned = "<B>ERROR in Response xml:<BR>ERROR DETAILS:</B><BR><HR><BR>" 
end if

dim nodeList
Set nodeList = xmlDoc.SelectNodes("xmldata/customers")

For Each itemAttrib In nodeList
    dim custID, custLname, custFname    
    custID =itemAttrib.selectSingleNode("customerid").text
    custLname =itemAttrib.selectSingleNode("lastname").text
    custFname =itemAttrib.selectSingleNode("firstname").text
    response.write("News Subject: " & custID)
    response.write("<br />News Subject: " & custLname)
    response.write("<br />News Date: " & custFname)
Next

The result of the code above is zilch! nothing is written to the page. One strange thing is if I select the root element and get its length as follows;

Set nodeList = xmlDoc.SelectNodes("xmldata")
Response.Write(nodeList.length) '1 is written to page

It correctly determines the length of 1. However when I try the same with the next node down as follows;

Set nodeList2 = xmlDoc.SelectNodes("xmldata/customers")
Response.Write(nodeList.length) '0 is written to page

It returns a length of 0. WHY!

Please note that this isn't the only way I have attempted to access the values of these nodes. I just can not work out what I am doing wrong. Could someone please help me out. Cheers.

urbanMethod
  • 55
  • 1
  • 1
  • 4

3 Answers3

2

Short answer

oXMLHttp.ResponseXML.text may return some text, but not 'A string containing a URL that specifies the location of the XML file' as required for the parameter of .load. So replace

xmlDoc.load (oXMLHttp.ResponseXML.text)

with

xmlDoc.loadXml oXMLHttp.ResponseXML.xml

If that 'does not work', say so; I then will try to provide a longer answer.

(P.S. to the short answer: AnthonyWJones' advice not to transform the XML twice is sound; I offered this 'minimal impact on existing code' approach in the hope to get the OT over the first hurdle, not as a generally applicable strategy.)

Longer answer

If you have XML problems on an ASP page, you should try to isolate and test the XML specific problems in a console script. For your problem I filled a skeleton (load .xml file, check for errors) with code to access nodes via XPath and DOM tree:

  Dim oFS    : Set oFS  = CreateObject( "Scripting.FileSystemObject" )
  Dim sFSpec : sFSpec   = oFS.GetAbsolutePathName("..\data\00.xml")
  Dim oXml   : Set oXml = CreateObject("Msxml2.DOMDocument")

  oXml.setProperty "SelectionLanguage", "XPath"
  oXml.async = False
  oXml.load sFSpec

  If 0 = oXml.parseError.errorCode Then
     WScript.Echo "loaded:", sFSpec
     WScript.Echo "root:", oXml.documentElement.tagName

     Dim sXPath, ndlFnd, ndChild, ndFnd

     sXPath = "/xmldata/customers"
     Set ndlFnd = oXml.selectNodes(sXPath)
     If 0 = ndlFnd.length Then
        WScript.Echo "no '" & sXPath & "' found"
     Else
        WScript.Echo "found", ndlFnd.length, "node(s) for '" & sXPath & "'"
        sXPath = "firstname"
        For Each ndChild In ndlFnd
            WScript.Echo "child:", ndChild.tagName
            Set ndFnd = ndChild.selectSingleNode(sXPath)
            If ndFnd Is Nothing Then
               WScript.Echo "no '" & sXPath & "' found"
            Else
               WScript.Echo ndFnd.text, "==", ndChild.childNodes(1).text
            End If
        Next
     End If
  Else
     WScript.Echo "errorCode:", oXml.parseError.errorCode
     WScript.Echo oXml.parseError.reason
  End If

output:

loaded: E:\trials\SoTrials\answers\11166940\data\00.xml
root: xmldata
found 1 node(s) for '/xmldata/customers'
child: customers
Jim == Jim

As you can see

  1. I use standard/approved methods to check the result of the single steps (e.g. parseError (instead of voodoo length test) to see if I got a well-formed/valid/usable document)
  2. When in doubt, I put in a WScript.Echo to make sure my assumptions about what VBScript should deliver hold water.
Ekkehard.Horner
  • 38,498
  • 2
  • 45
  • 96
  • Hi Ekkerhard, thanks for the reply. I have tried what you have suggested and I am still having the same problem trying to select anything deeper than the xmldata node. – urbanMethod Jun 23 '12 at 08:40
  • Cheers for the extended answer. I worked out my issue was related to case sensitivity(I have posted the details). I will be sure to have a crack at the console script you posted next time I run into XML issues. – urbanMethod Jun 23 '12 at 11:59
2

First off stop doing this:

Dim doc : Set xmlDoc = CreateObject("MSXML2.DOMDocument")
xmlDoc.LoadXML (oXmlHttp.responseXML.xml)

XML in the response is parsed into a DOM, which you then ask to be converted back into a string (.xml) which then parse (again) into another DOM (.LoadXML).

Do simply this:

Dim xmlDoc : Set xmlDoc = oXmlHttp.responseXML

Secondly you are correct in your answer XPath is case-sensitive so your XPaths (apart from the .text goof which Ekkehard has already pointed out) wouldn't work because the xml you are getting didn't match what you thought you were getting.

Finally the definition of "Camel casing" is does vary but generally this "postalAddress" is camel cased and this "PostalAddress" is refered to as "Pascal casing".

AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • Thanks Anthony for your reply. However, I still don't have the answer to the real issue that caused me main problem being why all the tags where made lower case. I say this because all the code errors that have been pointed out are really due to me experimenting and it didn't cause the problem. ps. Would of saying Upper Camel Case appeased you? :) – urbanMethod Jun 24 '12 at 06:35
  • I'm not sure how you found that something "made all the tags lower case"? MSXML doesn't do that. Perhaps if you described in detail _exactly_ how you managed to observe this phenomenon. – AnthonyWJones Jun 24 '12 at 17:53
0

Ok, so I finally worked out what I was doing wrong. As the xml I was retrieving was from a webservice, and I had limited information about it, I used the following to write the xml to the page so that I could see how it was structured.

Response.Write oXMLHttp.ResponseXml.xml

For some reason(maybe someone could fill this part in) it wrote all the XML tags in lower case. It turns out that after some investigation and after doing the following I found out that this was not the truth!

dim nodeList
Set nodeList = xmlDoc.SelectNodes("//xmldata/")

for each item In nodeList
    response.write(item.text & " -> Tag Name: " & item.nodeName & "<br />")
Next

'this wrote the following to the page
'22506 -> Tag Name: CustomerID
'Jim -> Tag Name: FirstName
'N -> Tag Name: IsSuperAdmin
'Jones 2 -> Tag Name: LastName

As you can see the 'nodeName' property output shows the tags to be camel case. So that ResponseXML was rather misleading and seeing XPath is case sensitive was preventing me from selecting the Nodes in question.

urbanMethod
  • 55
  • 1
  • 1
  • 4