VBScript无法选择XML节点

时间:2012-06-23 04:48:55

标签: xml asp-classic vbscript msxml

我试图从某些webservice响应XML中选择节点无济于事。出于某种原因,我能够选择根节点(“xmldata”)但是,当我尝试深入钻取(“xmldata / customers”)时,所有内容都返回空!下面是Web服务返回的XML示例。

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

这是我试图选择customerid,firstname和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

上面代码的结果是zilch!没有写入页面。一个奇怪的事情是,如果我选择根元素并获得其长度如下;

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

它正确地确定了1的长度。但是当我尝试下一个节点时,如下所示;

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

它的长度为0.为什么!

请注意,这不是我尝试访问这些节点值的唯一方法。我无法弄清楚我做错了什么。请有人帮帮我。干杯。

3 个答案:

答案 0 :(得分:2)

简短回答

oXMLHttp.ResponseXML.text可能会返回一些文本,但不会返回“包含指定XML文件位置的URL的字符串”,这是.load参数所需的。所以替换

xmlDoc.load (oXMLHttp.ResponseXML.text)

xmlDoc.loadXml oXMLHttp.ResponseXML.xml

如果“不起作用”,请说出来;然后我会尝试提供更长的答案。

(PS简短回答:AnthonyWJones的建议将XML转换两次是合理的;我提出这种'对现有代码的影响微乎其微',希望能够让OT超过第一个障碍,而非普遍适用的策略。)

更长的答案

如果在ASP页面上存在XML问题,则应尝试在控制台脚本中隔离并测试XML特定问题。对于您的问题,我用代码填充了一个框架(加载.xml文件,检查错误),以通过XPath和DOM树访问节点:

  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

输出:

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

如你所见

  1. 我使用标准/已批准的方法来检查单个步骤的结果(例如parseError(而不是巫毒长度测试),看看我是否有一个格式正确/有效/可用的文档)
  2. 如果有疑问,我会加入一个WScript.Echo,以确保我对VBScript应该提供的内容有所保留。

答案 1 :(得分:2)

首先停止这样做:

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

将响应中的XML解析为DOM,然后将其转换回字符串(.xml),然后再将其解析为另一个DOM(.LoadXML)。

只需这样:

Dim xmlDoc : Set xmlDoc = oXmlHttp.responseXML

其次你的答案是正确的XPath是区分大小写的,所以你的XPath(除了Ekkehard已经指出的.text goof)不会起作用,因为你得到的xml与你认为的不一致得到了。

最后“Camel casing”的定义确实有所不同,但一般来说这个“postalAddress”是骆驼套装,而这个“PostalAddress”被称为“Pascal套管”。

答案 2 :(得分:0)

好的,所以我终于搞清楚我做错了什么。由于我正在检索的xml来自web服务,并且我的信息有限,我使用以下内容将xml写入页面,以便我可以看到它的结构。

Response.Write oXMLHttp.ResponseXml.xml

出于某种原因(可能有人可以填写此部分),它以小写形式编写了所有XML标记。事实证明,经过一些调查,经过以下调查后我发现这不是事实!

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

正如您所看到的,'nodeName'属性输出显示标记为camel case。因此,ResponseXML相当误导,并且看到XPath区分大小写阻止我选择有问题的节点。