【问题标题】:Procedure result with XML parsing error带有 XML 解析错误的过程结果
【发布时间】:2016-08-21 23:55:47
【问题描述】:

我正在尝试使用我的第一个程序。我需要它用于谷歌矩阵。这是我的程序,在那里找到

CREATE PROCEDURE [dbo].[CalculateDistanceGoogle] 
    (@ToAddress NVARCHAR(100), 
     @FromAddress NVARCHAR(100), 
     @DistanceistanceInKm FLOAT OUTPUT) 
AS
BEGIN
    DECLARE @Object INT 
    DECLARE @ResponseonseText NVARCHAR(4000) 
    DECLARE @StatuserviceUrl NVARCHAR(500)

    SET @StatuserviceUrl = 'http://maps.googleapis.com/maps/api/distancematrix/xml?origins=' + @ToAddress + '&destinations=' + @FromAddress +'&mode=driving&language=it-IT&units=metric;'

    EXEC sp_OACreate 'MSXML2.XMLHTTP', @Object OUT; EXEC sp_OAMethod @Object, 'open', NULL, 'get', @StatuserviceUrl, 'false' EXEC sp_OAMethod @Object, 'send' EXEC sp_OAMethod @Object, 'responseText', @ResponseonseText OUTPUT

    DECLARE @Response XML

    SET @Response = CAST(CAST(@ResponseonseText AS NVARCHAR(MAX)) AS XML)

    DECLARE @Status NVARCHAR(20) DECLARE @Distance NVARCHAR(20)

    SET @Status = @Response.value('(DistanceMatrixResponse/row/element/status)[1]', 'NVARCHAR(20)')

    IF(@Status = 'ZERO_RESULTS') 
       SET @Distance = NULL 
    ELSE 
       SET @Distance = @Response.value('(DistanceMatrixResponse/row/element/distance/value)[1]', 'NVARCHAR(20)')

    SET @DistanceistanceInKm = ROUND(CAST(@Distance AS FLOAT) / 1000, 1)

    PRINT @DistanceistanceInKm
END

这是将距离结果存储在变量中的执行:

DECLARE @Distanza NVARCHAR 
EXEC @Distanza = dbo.CalculateDistanceGoogle @ToAddress = 'CITY', @FromAddress='CITY',  @DistanceistanceInKm = @Distanza
PRINT @Distanza

我收到此错误:

消息 9402,级别 16,状态 1,过程 CalculateDistanceGoogle,行 13
XML解析:第1行,第38个字符,无法切换编码

你能帮我理解为什么吗?

谢谢!

【问题讨论】:

    标签: parsing stored-procedures sql-server-2005


    【解决方案1】:

    主要问题是 Google 返回编码为 UTF-8 的 XML,而 SQL Server 仅处理和存储 XMLNVARCHAR / NCHAR 数据的 UTF-16(小尾数)。

    我使用了以下网址:

    http://maps.googleapis.com/maps/api/distancematrix/xml?origins=Boise+ID&destinations=Casper+WY&mode=driving&language=en-US
    

    并收到以下回复:

    <?xml version="1.0" encoding="UTF-8"?>
    <DistanceMatrixResponse>
     <status>OK</status>
     <origin_address>Boise, ID, USA</origin_address>
     <destination_address>Casper, WY, USA</destination_address>
     <row>
      <element>
       <status>OK</status>
       <duration>
        <value>36626</value>
        <text>10 hours 10 mins</text>
       </duration>
       <distance>
        <value>1103852</value>
        <text>1,104 km</text>
       </distance>
      </element>
     </row>
    </DistanceMatrixResponse>
    

    因此,从非常简单的意义上说,您可以通过简单地从 XML 文档中删除 encoding="UTF-8" 字符串,然后将其转换为 XML 来“解决”这个问题。您可以通过在 SET @Response = CAST(... 行上方添加以下行来做到这一点:

    SET @ResponseonseText = REPLACE(@ResponseonseText, N'encoding="UTF-8"', N'');
    

    请记住,以 UTF-8 格式传输的某些字符可能在存储在 NVARCHAR 变量中时会被损坏。但也许这部分已经被sp_OAMethod 处理了,在这种情况下你不需要担心。

    还有:

    • 根据Google API docs,您应该传入一个API“key”参数。但不知何故,如果没有它,它似乎确实可以工作,至少在有限的意义上。
    • 您应该考虑放弃sp_OA* OLE 自动化过程,因为它们在引入 SQL Server 2005 时已被弃用。首选是将此类功能移至 SQLCLR。 (当然,如果您仍在使用 SQL Server 2005,那么它现在也已被弃用了一段时间;-)
    • 即使在存储过程退出时应该自动清理 OLE 对象,添加以下行可能仍然是个好主意:sp_OADestroy@Object
    • @ResponseonseText 应声明为NVARCHAR(MAX)
    • 您应该删除CASTNVARCHAR(MAX)@ResponseonseText,因为它没有用。即使您必须将该变量保留为 NVARCHAR(4000)CASTMAX 也不会真正做任何事情。
    • 您可能希望在存储过程顶部添加SET NOCOUNT ON;,紧跟在BEGIN 之后。
    • 您应该将其包装在 TRY...CATCH 构造中。

    【讨论】:

    • - 我添加了 UTF 8 行替换,现在它没有给我错误,但我的打印结果 = 0。还有什么问题? - 我需要如何用 SQLCLR 替换 sp_OA?如果我直接替换它,它会给我一个未创建表的错误。
    • - 我已经删除了演员表 - 我已经设置了 nocount - 我不明白为什么要尝试捕获?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    相关资源
    最近更新 更多