Набор строк XML и MsXML2 - PullRequest
       36

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

1 голос
/ 27 января 2012

У меня есть набор строк, возвращающийся с использованием схемы набора строк 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 ]

1 голос
/ 27 января 2012

Предположим, что отправленный вами 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
1 голос
/ 27 января 2012

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

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 в SelectionNamespaces
  • Загрузите файл, проверьте ошибки
  • Укажите выражения XPath (осторожно !, попробуйте «перевести» XML из вашего образца в XPATH)
  • Проверьте результаты .selectSingleNode () и .selectNodes ()
  • Доступ к атрибутам, содержащим данные
...