Получение атрибута XML на основе другого атрибута в VBScript

У меня есть следующий XML, который был возвращен из SOAP API:

<?xml version="1.0" encoding="UTF-8"?>
<results>
<result>
<field name="accountnumber" value="100035" />
<field name="occupantcode" value="11" />
<field name="otherfield" value"do not care about this one" />
</result>
</results>

Я пытаюсь загрузить номер счета в переменную с именем AcctNum, а другой — в OccCode, используя VBScript. Я очень новичок в запросах XPath. Я пытаюсь что-то вроде этого:

Set ANumNode = xmlResponse.SelectNodes("//results/result/field[@accountnumber]")
For Each objSite In ANumNode
  AcctNum = objSite.SelectSingleNode("accountnumber").Text
Next

но, конечно, это эффектно взрывается. На самом деле в ответе около 20 узлов полей, из которых меня интересуют только 4 из них. Я не могу изменить формат выводимого XML.


person dcoughler    schedule 17.04.2017    source источник
comment
Я могу предложить вам только частичный ответ, так как мой VB Script более чем ржавый. Чтобы получить номер учетной записи, используемый xpath будет (может) быть //field[@name='accountnumber'] и, соответственно, //field[@name='occupantcode'], который будет возвращать узлы соответственно, из которых вы должны иметь возможность для извлечения текстовых значений. Все, что сверх этого, было бы моим предположением. Надеюсь, поможет.   -  person Bill Hileman    schedule 17.04.2017
comment
Взрыв эффектно немного неспецифичен. Что точно не работает должным образом? Какой результат вы ожидали? Какой результат вы на самом деле получили? Вы получили сообщение об ошибке? Что это говорит?   -  person Ansgar Wiechers    schedule 18.04.2017
comment
Эффектный взрыв в этом случае не дает никаких результатов после многократной попытки.   -  person dcoughler    schedule 18.04.2017


Ответы (2)


  1. Ваш XML неправильно сформирован.
  2. Вам нужно понимать различия между узлами и атрибутами

Используйте документы (начать здесь), чтобы работать с этим примером кода:

Option Explicit

Dim oFS    : Set oFS  = CreateObject( "Scripting.FileSystemObject" )
Dim sFSpec : sFSpec   = oFS.GetAbsolutePathName(".\43459134.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, ndlResults, ndResult

   sXPath = "/results/result"
   Set ndlResults = oXml.selectNodes(sXPath)
   If 0 = ndlResults.length Then
      WScript.Echo "no '" & sXPath & "' found"
   Else
      WScript.Echo "found", ndlResults.length, "node(s) for '" & sXPath & "'"
      For Each ndResult In ndlResults
         WScript.Echo "ndResult.tagName:", ndResult.tagName
         Dim AcctNum : AcctNum = ndResult.selectSingleNode("field[@name=""accountnumber""]").getAttribute("value")
         Dim OccCod  : OccCod  = ndResult.selectSingleNode("field[@name=""occupantcode""]").getAttribute("value")
         WScript.Echo AcctNum, OccCod
      Next
   End If
Else
   WScript.Echo "errorCode:", oXml.parseError.errorCode
   WScript.Echo oXml.parseError.reason
End If

Выход:

cscript 43459134.vbs
loaded: E:\work\proj\soa\tmp\43459134.xml
root: results
found 1 node(s) for '/results/result'
ndResult.tagName: result
100035 11

Обновление комментариев:

Сценарий «работает» для (исправленного) .xml, который вы опубликовали; если /results/result находится ниже по дереву, попробуйте /REALDOCROOT/pi/pa/pi/results/result или менее конкретное //results/result. Или еще: опубликуйте реальный ввод.

person Ekkehard.Horner    schedule 18.04.2017
comment
К сожалению, я не нашел /result/results. Это было после того, как живой ответ был сохранен в файл и прочитан обратно. - person dcoughler; 18.04.2017

В итоге я отказался от XPath-запросов и вместо этого создал свой собственный синтаксический анализатор, поскольку структура должна была быть статической:

Function retrieveValue(XMLblock, fieldname)
  start = 1
  '***Find field
  start = InStr(start, XMLBlock, "" & fieldname & "")
  '***Find value tag
  start = InStr(start, XMLBlock, "value")
  '***Find end quote for value
  endquote = InStr(start+7, XMLBlock, """")
  retrieveValue = Mid(XMLBlock, start+7, endquote-start-7)
End Function

Не самый элегантный код, но он работает, так что я могу продолжить свой проект. Спасибо всем за вашу помощь.

person dcoughler    schedule 18.04.2017
comment
Это не просто не самый элегантный код. Возможно, это наихудший из возможных подходов. - person Ansgar Wiechers; 23.04.2017