VBScript не может выбирать узлы XML

Я пытаюсь выбрать узлы из некоторого XML-ответа веб-службы, но безрезультатно. По какой-то причине я могу выбрать корневой узел («xmldata»), однако, когда я пытаюсь углубиться в детали («xmldata / customers»), все возвращается пустым! Ниже приведен образец XML, возвращаемого веб-службой.

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

и вот код, который я пытаюсь выбрать по индивидуальному заказу, имени и фамилии;

' 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

Результат кода выше - пшик! на страницу ничего не пишется. Одна странная вещь - если я выберу корневой элемент и получу его длину следующим образом:

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. ПОЧЕМУ!

Обратите внимание, что это не единственный способ получить доступ к значениям этих узлов. Я просто не могу понять, что делаю не так. Может ли кто-нибудь помочь мне. Ваше здоровье.


person urbanMethod    schedule 23.06.2012    source источник


Ответы (3)


Во-первых, прекратите это делать:

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 (кроме ошибки .text, на которую уже указал Эккехард) не будут работать, потому что xml, который вы получаете, не соответствует тому, что вы думали, что получаете.

Наконец, определение «верблюжьего регистра» действительно различается, но обычно этот «почтовый адрес» имеет регистр верблюда, а этот «почтовый адрес» упоминается как «регистр Паскаля».

person AnthonyWJones    schedule 23.06.2012
comment
Спасибо Энтони за ответ. Однако у меня до сих пор нет ответа на реальную проблему, которая вызвала у меня главную проблему: почему все теги сделаны в нижнем регистре. Я говорю это потому, что все указанные ошибки кода на самом деле связаны с моими экспериментами, и это не вызвало проблемы. пс. Вы бы успокоили вас, сказав, что случай Верхнего верблюда? :) - person urbanMethod; 24.06.2012
comment
Я не уверен, как вы обнаружили, что что-то делает все теги строчными? MSXML этого не делает. Возможно, если вы подробно описали именно, как вам удалось наблюдать это явление. - person AnthonyWJones; 24.06.2012

Краткий ответ

oXMLHttp.ResponseXML.text может возвращать некоторый текст, но не «Строку, содержащую URL-адрес, указывающий местоположение файла XML», как требуется для параметра .load. Так что замените

xmlDoc.load (oXMLHttp.ResponseXML.text)

с участием

xmlDoc.loadXml oXMLHttp.ResponseXML.xml

Если это «не работает», так и скажите; Затем я постараюсь дать более подробный ответ.

(PS к короткому ответу: совет AnthonyWJones не преобразовывать XML дважды - разумный; я предложил этот подход «минимального воздействия на существующий код» в надежде преодолеть первое препятствие OT, а не как общеприменимая стратегия.)

Более длинный ответ

Если у вас есть проблемы с XML на странице ASP, вы должны попытаться изолировать и протестировать специфические проблемы 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, выдерживают критику.
person Ekkehard.Horner    schedule 23.06.2012
comment
Привет Эккерхард, спасибо за ответ. Я попробовал то, что вы предложили, и у меня все еще та же проблема, пытаясь выбрать что-то более глубокое, чем узел xmldata. - person urbanMethod; 23.06.2012
comment
Приветствую за развернутый ответ. Я понял, что моя проблема связана с чувствительностью к регистру (подробности я опубликовал). Я обязательно попробую написать сценарий консоли, который вы опубликовали, в следующий раз, когда я столкнусь с проблемами XML. - person urbanMethod; 23.06.2012

Итак, я наконец понял, что делаю не так. Поскольку xml, который я получал, был из веб-службы, и у меня была ограниченная информация о нем, я использовал следующее, чтобы записать 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' теги отображаются в верблюжьем регистре. Таким образом, ResponseXML вводил в заблуждение, а то, что XPath чувствителен к регистру, не позволяло мне выбрать рассматриваемые узлы.

person urbanMethod    schedule 23.06.2012