I'm parsing an xml file but have problem with cyrillic characters:
this is the relevant part of the stored Procedure
SOAP input to parse:
'<?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>'
Stored Procedure
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
the problem is that @S looks like this
INSERT INTO Sales.dbo.ShippingAddress ([Name],[Street1],ShippingAddressID)
VALUES
(N'Polydoros Sample',N'??????? ?????? ??? 4 ?????? 1 ???????? 12','KkQ0LhbhwXfzi+Ko1Ai6s+SDZRT2kYhYC3vM2x2TB5Y=')
where Cyrillic Charachters are transformed into ???
I put the N before all input but problem is clearly before:
I can suppose is in the
T.X.value(N'text()[1]', 'nvarchar(max)')
but I do not know how solve it.
Can suggest a solution?
Thanks
Your DECLARE @XML
line is wrong. The string literal needs to be prefixed with a capital N
. The characters are getting converted to ? in the interpretation of that literal.
Also, you have not prefixed all string literals with a capital-N
, but you have at least one of them prefixed (the first one in the SET @S = N'
line, and so the rest of the literals (which are VARCHAR
without the N
prefix) will be implicitly converted to NVARCHAR
.
The following adaptation of your updated code shows this behavior, and how placing the N
prefix on the input string (prior to calling the Stored Procedure) fixes the problem:
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;
Also, SQL Server XML does not ever store the <?xml ... ?>
declaration line, so you might as well remove it from the beginning of the literal value.
First of all: If this solves your problem, please accept srutzky's answer, it is the correct answer to solve your initial example with the declared variable. (but you may vote on this :-) ).
This is just an example to show the problem:
Try this
SELECT 'Луговой проезд'
SELECT N'Луговой проезд'
And now try this:
CREATE PROCEDURE dbo.TestXML(@xml XML)
AS
BEGIN
SELECT @xml;
END
GO
EXEC dbo.TestXML '<root><Street>Луговой проезд дом 4 корпус 1 квартира 12</Street></root>';
returns
<root>
<Street>??????? ?????? ??? 4 ?????? 1 ???????? 12</Street>
</root>
While this call (see the leading "N")
EXEC dbo.TestXML N'<root><Street>Луговой проезд дом 4 корпус 1 квартира 12</Street></root>';
returns
<root>
<Street>Луговой проезд дом 4 корпус 1 квартира 12</Street>
</root>
Conclusio
This does not happen within your procedure. The string you pass over to the stored procedure is wrong before you even enter the SP.