XML 行集和 MsXML2

发布于 2024-12-29 10:50:42 字数 834 浏览 2 评论 0原文

我有一个使用 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(...)' 

这可能是我做的事情完全错误,如果是这样,请有人向我指出,因为我已经盯着它看了两个小时,但我无法理解。

I have a rowset coming back using the Microsoft rowset schema from my stock control system.

However when using msxml2 to read the document I don't seem to be able to access the data (Written in vbscript)

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

To pull this back I am using:

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")

However I am receiving the following message:

Microsoft VBScript runtime error '800a01a8'

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

This is probably me doing something totally wrong, if so could someone point it out to me please because I have stared at this for 2 hours now and I can't get it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

稀香 2025-01-05 10:50:42

给定一个如下表:

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.dom文档
  • 对其进行配置;特别是将命名空间从 xml 标记复制到
    SelectionNamespaces
  • 加载文件,检查错误
  • 指定您的 XPath 表达式(小心!,尝试将示例中的 XML“翻译”为 XPATH)
  • 检查 .selectSingleNode() 和 .selectNodes() 的结果
  • 访问保存数据的属性

Given a table like:

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|
----------------------------------------------------------------

in an ADO (classic, tested with version 2.8) accessible database, you
can save the resultset to XML using

  oRS.Save sFSpec, adPersistXML

That gives you XML like:

<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>

To read that data, start with (local, console) code like:

  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

The important steps:

  • For developing/testing avoid the extra complexity of using a server;
    if cscript readxml.vbs succeeds, it's easy to 'port' the working code
    to .asp (and deal with server specific problems separately)
  • Create an msxml2.domdocument
  • Configure it; especially copy the namespaces from the xml tag to the
    SelectionNamespaces
  • Load the file, check for errors
  • Specify your XPath expressions (carefully!, try to 'translate' XML from your sample to XPATH)
  • Check the results of .selectSingleNode() and .selectNodes()
  • Access the attributes holding the data
昔日梦未散 2025-01-05 10:50:42

让我们假设您发布的 XML a) 包含正确的命名空间别名,b) 它已正确加载到 XML_response 中。

现在“正确”的方法是使用 XPath,但是在这种情况下我们可以使用更简单的代码来实现我们的目标。 MSXML(3 或更低版本)中的默认选择语言是 XSL 模式,此选择不理解命名空间别名,因此 的标记名称为“rs: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

Lets assume the XML you posted a) includes correct namespace aliases and b) that it has loaded in XML_response correctly.

Now the "correct" way to do this is use XPath however we can achieve our goals with simpler code in this case. The default selection language in MSXML (3 or below) is XSL Pattern, this selection doesn't understand namespace aliases, so the <rs:data> has the tag name "rs:data" not "data" from its point of view. So thats the first thing you are doing wrong.

Another thing is that getElementsByTag is returning a collection of nodes, which contains just one node the "rs:data". Your code is trying to read the "field" attribute from that node where in fact it on a child node of "z:row".

Here is what you code should look like:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文