无法在XML asp经典中获得具体价值

时间:2014-01-23 05:08:23

标签: vbscript asp-classic xml-parsing

我从http POST获取XML对象。 XML看起来像这样。

<GetTransactionResponse xmlns="http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <Errors xmlns:a="http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.DCO"/>
      <TransactionStatusCode>Completed</TransactionStatusCode>
      <Transaction xmlns:a="http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.DCO">
            <a:AmountPaid>5.00</a:AmountPaid>
             ....
      </Transaction>
 </GetTransactionResponse>

这是我检索XML的代码:

Dim x: Set x = CreateObject("Microsoft.XMLHTTP")
x.Open "GET", "http://localhost/tutorial/poli/success.php?token=2uBddM5Mw0ip91Wx7akcuT5btzwoxRUM", false
'x.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
x.Send()

If x.status = 200 Then
    Dim docXML
    Set docXML = server.CreateObject( "MSXML2.DomDocument.6.0" ) 
    docXML.async = False 
    docXML.loadXML( x.responseText )    
    docXML.setProperty "SelectionNamespaces", "xmlns:a='http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.DCO' xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns:='http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.Contracts'"

现在我可以从AmountPaid获取数据如下:

dim obj1
set obj1 = docXML.selectSingleNode( "//a:AmountPaid" )
Response.write obj1.text

但是当我得到TransactionStatusCode我失败了,错误'对象需要' 这是我如何尝试得到它:

dim obj1
set obj1 = docXML.selectSingleNode( "/TransactionStatusCode" )
Response.write obj1.text

请向我解释为什么它没有成功,以及如何获得它。提前致谢

1 个答案:

答案 0 :(得分:3)

使用高度结构化的XML时,您应该在XPath查询中使用完整的路径,例如

set obj1 = docXML.selectSingleNode( "/GetTransactionResponse/TransactionStatusCode" )

'catch all'“// whatever”适用于结构较少的XML(也许是.xhtml文档),其中whatevers可以在不同级别/任何地方找到。

所以

中添加缺少的“/”
set obj1 = docXML.selectSingleNode( "/TransactionStatusCode" )

更新wrt评论:

是的,这是一个命名空间问题 - 根据How to use XPath to query against a user-defined default namespace,它完全是设计的。

您需要为“SelectionNamespaces”属性中的默认命名空间指定名称,并在查询中使用tha name。在代码中:

Option Explicit

  Dim sXML : sXML = Join(Array( _
      "<GetTransactionResponse xmlns=""http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.Contracts"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">" _
    , "<Errors xmlns:a=""http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.DCO""/>" _
    , "<TransactionStatusCode>Completed</TransactionStatusCode>" _
    , "<Transaction xmlns:a=""http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.DCO"">" _
    , "     <a:AmountPaid>5.00</a:AmountPaid>" _
    , "</Transaction>" _
    , "</GetTransactionResponse>" _
  ), vbCrLf)

' !! http://support.microsoft.com/kb/288147/en-us
  Dim oXDoc  : Set oXDoc = CreateObject("Msxml2.DOMDocument.6.0")
  oXDoc.setProperty "SelectionLanguage", "XPath"
' Dim sNS : sNS = "xmlns:a='http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.DCO' xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns:='http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.Contracts'"
  Dim sNS : sNS = "xmlns:a='http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.DCO' xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns:wtf='http://schemas.datacontract.org/2004/07/Centricom.POLi.Services.MerchantAPI.Contracts'"
' ---------------------------------------------------------------------------------------------------------------------------------------------------------------------^
  oXDoc.setProperty "SelectionNamespaces", sNS
  oXDoc.async = False
  oXDoc.loadxml sXml
  If 0 = oXDoc.ParseError Then
     WScript.Echo "ready to process"
     Dim sXPath
     For Each sXPath In Array( _
          "/GetTransactionResponse/TransactionStatusCode" _
        , "/wtf:GetTransactionResponse/wtf:TransactionStatusCode" _
        , "/wtf:GetTransactionResponse/wtf:Transaction/a:AmountPaid" _
     )
       Dim ndFnd  : Set ndFnd = oXDoc.SelectSingleNode(sXPath)
       If ndFnd Is Nothing Then
          WScript.Echo sXpath, "not found"
       Else
          WScript.Echo sXpath, "=>", ndFnd.text
       End If
     Next
  Else
     WScript.Echo oXDoc.parseError.reason
  End If

输出:

cscript 21299850.vbs
ready to process
/GetTransactionResponse/TransactionStatusCode not found
/wtf:GetTransactionResponse/wtf:TransactionStatusCode => Completed
/wtf:GetTransactionResponse/wtf:Transaction/a:AmountPaid => 5.00