如何从T-SQL读取xml响应?

时间:2015-06-03 11:06:17

标签: xml web-services tsql stored-procedures

我有这个Store Procedure来调用和读取来自Web服务的响应。我从商店程序调用Web服务。 我尝试阅读回复时遇到问题。所以代码是这样的:

SET @Response=
    '
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body>
            <RegisterUserResponse xmlns="http://tempuri.org/">
                <RegisterUserResult>DRnGXcT2gFTTxta4+ohnVx30Q1UL7N8gUqx0zpYMtMqmgwhkHmmXRWSoHu+Ghk0x</RegisterUserResult>
            </RegisterUserResponse>
        </soap:Body>
    </soap:Envelope>'

    declare @iXDoc int
    EXEC sp_xml_preparedocument @iXDoc OUTPUT, @Response

    select *
    from openxml(@iXDoc, '/Envelope/Body/RegisterUserresponse/RegisterUserResult',2)

我的结果是空的。如果我尝试在

中更改查询
select *
        from openxml(@iXDoc, '',2)

我有结果,但对我来说不合适。

1 个答案:

答案 0 :(得分:1)

您的XML有两个重要的命名空间;在根元素处声明的soap名称空间和在<RegisterUserResponse>元素处声明的默认名称空间。因此,您需要将名称空间前缀映射作为sp_xml_preparedocument

的参数传递
declare @nsmap varchar(200) = '<root xmlns:d="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>'
declare @iXDoc int
EXEC sp_xml_preparedocument @iXDoc OUTPUT, @Response, @nsmap

然后在xpath中正确使用映射的前缀:

select *
from openxml(@iXDoc, '/soap:Envelope/soap:Body/d:RegisterUserResponse/d:RegisterUserResult',2)

如果可能在您使用的SQL Server版本中,总是更喜欢使用本机xquery从XML获取数据的更简洁方式,例如:

declare @Response varchar(max) = '
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body>
            <RegisterUserResponse xmlns="http://tempuri.org/">
                <RegisterUserResult>DRnGXcT2gFTTxta4+ohnVx30Q1UL7N8gUqx0zpYMtMqmgwhkHmmXRWSoHu+Ghk0x</RegisterUserResult>
            </RegisterUserResponse>
        </soap:Body>
    </soap:Envelope>'

;WITH XMLNAMESPACES 
(
    DEFAULT 'http://tempuri.org/',
    'http://schemas.xmlsoap.org/soap/envelope/' as soap
)
SELECT CAST(@Response AS XML).value('(/soap:Envelope/soap:Body/RegisterUserResponse/RegisterUserResult)[1]', 'varchar(max)')
  as 'RegisterUserResult'

<强> SQL Fiddle Demo