Набор строк XML и MsXML2

У меня есть набор строк, возвращаемый с использованием схемы набора строк Microsoft из моей системы управления запасами.

Однако при использовании msxml2 для чтения документа я не могу получить доступ к данным (написано в vbscript)

<xml>
    <s:schema>
        <!-- Schema here -->
    </s:schema>
    <rs:data>
        <z:row field="value" field1="value" />
    </rs:data>
</xml>

Чтобы вернуть это, я использую:

Set objXmlHttp = Server.CreateObject("Msxml2.ServerXMLHTTP")
objXmlHttp.open "POST", address, False
objXmlHttp.setRequestHeader "Content-Type", "text/xml"
objXmlHttp.Send strXml

Set objLst = XML_response.getElementsByTagName("data")
myValue = objLst.item(0).getAttribute("field")

Однако я получаю следующее сообщение:

Microsoft VBScript runtime error '800a01a8'

Object required: 'objLst.item(...)' 

Это, вероятно, я делаю что-то совершенно не так, если так, может кто-то указал мне, пожалуйста, потому что я смотрю на это в течение 2 часов, и я не могу понять это.

2 ответа

Решение

Учитывая таблицу как:

SELECT TOP 5 * FROM [actor.txt]
----------------------------------------------------------------
|actor_id|first_name|last_name   |last_update         |
|       1|PENELOPE  |GUINESS     |2/15/2006 4:34:33 AM|
|       2|NICK      |WAHLBERG    |2/15/2006 4:34:33 AM|
|       3|ED        |CHASE       |2/15/2006 4:34:33 AM|
|       4|JENNIFER  |DAVIS       |2/15/2006 4:34:33 AM|
|       5|JOHNNY    |LOLLOBRIGIDA|2/15/2006 4:34:33 AM|
----------------------------------------------------------------

в доступной базе данных ADO (классическая, протестированная с версией 2.8) вы можете сохранить набор результатов в XML, используя

  oRS.Save sFSpec, adPersistXML

Это дает вам XML как:

<xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
    xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
    xmlns:rs='urn:schemas-microsoft-com:rowset'
    xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
    <s:ElementType name='row' content='eltOnly'>
        <s:AttributeType name='actor_id' rs:number='1' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
            <s:datatype dt:type='i2' dt:maxLength='2' rs:precision='5' rs:fixedlength='true'/>
        </s:AttributeType>
        <s:AttributeType name='first_name' rs:number='2' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
            <s:datatype dt:type='string' dt:maxLength='45'/>
        </s:AttributeType>
        <s:AttributeType name='last_name' rs:number='3' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
            <s:datatype dt:type='string' dt:maxLength='45'/>
        </s:AttributeType>
        <s:AttributeType name='last_update' rs:number='4' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
            <s:datatype dt:type='dateTime' rs:dbtype='variantdate' dt:maxLength='16' rs:fixedlength='true'/>
        </s:AttributeType>
        <s:extends type='rs:rowbase'/>
    </s:ElementType>
</s:Schema>
<rs:data>
    <z:row actor_id='1' first_name='PENELOPE' last_name='GUINESS' last_update='2006-02-15T04:34:33'/>
    <z:row actor_id='2' first_name='NICK' last_name='WAHLBERG' last_update='2006-02-15T04:34:33'/>
    <z:row actor_id='3' first_name='ED' last_name='CHASE' last_update='2006-02-15T04:34:33'/>
    <z:row actor_id='4' first_name='JENNIFER' last_name='DAVIS' last_update='2006-02-15T04:34:33'/>
    <z:row actor_id='5' first_name='JOHNNY' last_name='LOLLOBRIGIDA' last_update='2006-02-15T04:34:33'/>
</rs:data>
</xml>

Чтобы прочитать эти данные, начните с (локального, консольного) кода, например:

  Dim oFS    : Set oFS   = CreateObject( "Scripting.FileSystemObject" )
  Dim sDDir  : sDDir     = oFS.GetAbsolutePathName( "..\Data" )
  Dim sFSpec : sFSpec    = oFS.GetAbsolutePathName( "..\Data\actor.xml" )
  Dim oXDoc  : Set oXDoc = CreateObject("msxml2.domdocument")
  Dim sXPath, ndFnd, ndlFnd, attrX, nIdx
  oXDoc.async             = False
  oXDoc.validateOnParse   = False
  oXDoc.resolveExternals  = False
  oXDoc.setProperty "SelectionLanguage", "XPath"
  oXDoc.setProperty "SelectionNamespaces", Join( Array( _
      "xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'" _
    , "xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'" _
    , "xmlns:rs='urn:schemas-microsoft-com:rowset'" _
    , "xmlns:z='#RowsetSchema'" _
 ), " ")
  If oXDoc.load(sFSpec) Then
     WScript.Echo sFSpec, "looks good."
     For Each sXPath In Array( _
              "/xml" _
            , "/xml/s:Schema" _
            , "/xml/rs:data" _
            , "/xml/rs:data/z:row[@actor_id=""2""]" _
         )
         WScript.Stdout.Write "|" & sXPath & "| => "
         Set ndFnd = oXDoc.selectSingleNode( sXPath )
         If ndFnd Is Nothing Then
            WScript.Stdout.WriteLine "not found"
         Else
            WScript.Stdout.WriteLine "found a(n) " & ndFnd.tagName
         End If
     Next
     WScript.Echo "-----------------------"

'<rs:data>
'   <z:row actor_id='1' first_name='PENELOPE' last_name='GUINESS' last_update='2006-02-15T04:34:33'/>
'       ...
'</rs:data>
     sXPath = "/xml/rs:data/z:row[@actor_id=""3""]"
     Set ndFnd = oXDoc.selectSingleNode( sXPath )
     If ndFnd Is Nothing Then
        WScript.Echo "|", sXPath, "| not found"
     Else
        For Each attrX In ndFnd.Attributes
            WScript.Echo attrX.Name, attrX.Value
        Next
     End If
     WScript.Echo "-----------------------"

     sXPath = "/xml/rs:data/z:row"
     Set ndlFnd = oXDoc.selectNodes( sXPath )
     If ndlFnd Is Nothing Then
        WScript.Echo "ndlFnd Is Nothing"
     Else
        If 0 = ndlFnd.Length Then
           WScript.Echo "ndlFnd is empty"
        Else
           For Each ndFnd In ndlFnd
               WScript.Echo TypeName(ndFnd)
               For Each attrX In ndFnd.Attributes
                   WScript.Echo "", attrX.Name, attrX.Value
               Next
           Next
        End If
     End If
  Else
     WScript.Echo "Bingo!"
     WScript.Echo oXDoc.parseError.reason
  End If

Важные шаги:

  • Для разработки / тестирования избегайте лишней сложности использования сервера; если cscript readxml.vbs успешно выполняется, легко "перенести" рабочий код на.asp (и отдельно решать специфичные для сервера проблемы)
  • Создайте msxml2.domdocument
  • Настройте это; особенно скопируйте пространства имен из тега xml в пространства имен SelectionName
  • Загрузите файл, проверьте на ошибки
  • Укажите выражения XPath (осторожно!, попробуйте "перевести" XML из вашего образца в XPATH)
  • Проверьте результаты.selectSingleNode() и.selectNodes()
  • Доступ к атрибутам, содержащим данные

Предположим, что опубликованный вами XML a) содержит правильные псевдонимы пространства имен и b) загружен в XML_response правильно.

Теперь "правильный" способ сделать это - использовать XPath, однако мы можем достичь наших целей с помощью более простого кода в этом случае. Язык выбора по умолчанию в MSXML (3 или ниже) - XSL Pattern, этот выбор не понимает псевдонимы пространства имен, поэтому <rs:data> имеет имя тега "rs:data", а не "data" с его точки зрения. Это первое, что вы делаете неправильно.

Другое дело, что getElementsByTag возвращает коллекцию узлов, которая содержит только один узел "rs:data". Ваш код пытается прочитать атрибут "field" из того узла, где он находится на дочернем узле "z:row".

Вот как должен выглядеть ваш код:

Dim objData: Set objData = XML_response.documentElement.selectSingleNode("rs:data") 

Dim row
Dim fieldVal, field1Val
For Each row in objData.selectNodes("z:row")
     fieldVal = row.getAttribute("field")
     field1Val = row.getAttribute("field1")

     ''# Do stuff with your fields for each row found.
Next
Другие вопросы по тегам