【问题标题】:SQL Server 2014 - Parsing XML with Cyrillic CharactersSQL Server 2014 - 使用西里尔字符解析 XML
【发布时间】:2017-07-29 15:11:18
【问题描述】:

我正在解析一个 xml 文件,但西里尔字符有问题:

这是存储过程的相关部分

要解析的 SOAP 输入:

'<?xml version="1.0"?>
<soapenv:Envelope xmlns:.......>
    <soapenv:Header>
    </soapenv:Header>
    <soapenv:Body>
        <GetResponse>
            <BuyerInfo>
              <Name>Polydoros Stoltidys</Name>
              <Street>Луговой проезд дом 4 корпус 1 квартира 12</Street>
            </BuyerInfo>
        </GetResponse>
    </soapenv:Body>
</soapenv:Envelope>'

存储过程

 CREATE PROCEDURE dbo.spXML_ParseSOAP
(
    @XML    XML
)
AS
SET NOCOUNT ON;
DECLARE @S nvarchar(max)='',
        @C  nvarchar(max)='',
        @D  nvarchar(max)=''


    SELECT 
        @C= IIF (CHARINDEX('['+T.X.value('local-name(.)', 'nvarchar(100)')+']',@C)=0, CONCAT( ISNULL(@C + ',','') , QUOTENAME(T.X.value('local-name(.)', 'nvarchar(100)'))), @C),
        @D= IIF (CHARINDEX('['+T.X.value('local-name(.)', 'nvarchar(100)')+']',@CP)=0, CONCAT( ISNULL(@D + ',N','') , '''',  T.X.value(N'text()[1]', 'nvarchar(max)'),''''), @D),
    FROM @XML.nodes('//*[count(child::*) = 0]') AS T(X)
    WHERE  T.X.value(N'local-name(.)', 'nvarchar(500)') 
    IN (select name from Customers.sys.columns where [object_id]=@O and is_identity=0)

    SET @S=N'INSERT INTO Sales.dbo.ShippingAddress ('+@C+',ShippingAddressID) VALUES ('+@D+','''+@FADR+''') 

    Print @S

问题是@S 看起来像这样

INSERT INTO Sales.dbo.ShippingAddress ([Name],[Street1],ShippingAddressID) 
VALUES 
(N'Polydoros Sample',N'??????? ?????? ??? 4 ?????? 1 ???????? 12','KkQ0LhbhwXfzi+Ko1Ai6s+SDZRT2kYhYC3vM2x2TB5Y=') 

西里尔字符转化为???

我将 N 放在所有输入之前,但问题显然在之前: 我可以假设是在

    T.X.value(N'text()[1]', 'nvarchar(max)')

但我不知道如何解决。

可以提出解决方案吗?

谢谢

【问题讨论】:

标签: sql-server character-encoding xml-parsing utf-16


【解决方案1】:

首先:如果这解决了您的问题,请接受 srutzky 的回答,用声明的变量解决您的初始示例是正确的答案。 (但您可以对此投票:-))。

这只是说明问题的一个例子:

试试这个

SELECT 'Луговой проезд'
SELECT N'Луговой проезд'

现在试试这个:

CREATE PROCEDURE dbo.TestXML(@xml XML)
AS
BEGIN
    SELECT @xml;
END
GO

EXEC dbo.TestXML '<root><Street>Луговой проезд дом 4 корпус 1 квартира 12</Street></root>';

返回

<root>
  <Street>??????? ?????? ??? 4 ?????? 1 ???????? 12</Street>
</root>

当这个调用时(见前导“N”)

EXEC dbo.TestXML N'<root><Street>Луговой проезд дом 4 корпус 1 квартира 12</Street></root>';

返回

<root>
  <Street>Луговой проезд дом 4 корпус 1 квартира 12</Street>
</root>

结论

不会发生在您的程序。在您输入 SP 之前,您传递给存储过程的字符串是错误的。

【讨论】:

    【解决方案2】:

    您的DECLARE @XML 行是错误的。字符串文字需要以大写字母 N 为前缀。字符正在转换为 ?在那个字面的解释中。

    此外,您还没有为所有字符串文字加上大写字母-N,但您至少有一个前缀(SET @S = N' 行中的第一个,其余的文字(即VARCHAR 没有N 前缀)将被隐式转换为NVARCHAR

    您更新后的代码的以下改编显示了这种行为,以及将N 前缀放在输入字符串上(在调用存储过程之前)如何解决问题:

    DECLARE @XML XML = N' <!-- remove the N from the left to get all ???? for "Street"-->
                <BuyerInfo>
                  <Name>Polydoros Stoltidys</Name>
                  <Street>Луговой проезд дом 4 корпус 1 квартира 12</Street>
                </BuyerInfo>
    ';
    
    
    DECLARE @S nvarchar(max)='',
            @C  nvarchar(max)='Street',
            @D  nvarchar(max)=''
    
    
        SELECT 
            @D= IIF (T.X.value('local-name(.)', 'nvarchar(100)') = N'Street',
                     T.X.value('./text()[1]', 'nvarchar(100)'),
                     @C)
        FROM @XML.nodes('//*[count(child::*) = 0]') AS T(X)
    
        SET @S=N'INSERT INTO Sales.dbo.ShippingAddress ('
               +  @C+',ShippingAddressID) VALUES (N'''+@D+''',''a'') '
    
        Print @S;
    

    此外,SQL Server XML 不会存储 &lt;?xml ... ?&gt; 声明行,因此您不妨从文字值的开头删除它。

    【讨论】:

    • 嗨,srutzky,实际上我没有@XML声明,现在我按原样修改了存储过程,对不起
    • @Joe 您仍然缺少输入字符串上的大写 N 前缀。我已经通过改编您更新的代码来更新我的答案,展示了它是如何工作的。
    • 对不起,但我不明白.. 我没有将@XML 声明为变量,而是作为输入字段,因此我应该写 `CREATE PROCEDURE dbo.spXML_ParseSOAP (@XML XML = N'')` ?因为我已经尝试过了,但结果..是一样的
    • @Joe 存储过程是如何被调用的?究竟从哪里来?
    • 您好,抱歉回复晚了。好吧 SP 是从一个 asp 页面调用的,但现在它似乎工作了,实际上它工作了.. 但我看不到我已经改变了什么 :-( 非常感谢!
    猜你喜欢
    • 2016-10-02
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    相关资源
    最近更新 更多