转换为SQL Server中具有特殊字符名称的XML

时间:2014-07-07 06:49:17

标签: sql sql-server xml sql-server-2008

在sql表中的数据类型VARCHAR(MAX)列中存在以下格式的XML

<?xml version="1.0" encoding="UTF-8"?>
<APIDATA xmlns="mynamespace"> 
<TRADE Action="Insert" CompanyID="33" Trader="Aleš Holubec" 
</TRADE>
</APIDATA>

我需要获取Action和CompanyID的属性值。即插入和33

在SQL中,我使用了以下查询

;WITH XMLNAMESPACES(DEFAULT 'mynamespace')

SELECT CONVERT(XML,column_name).value ('(APIDATA/TRADE/@Action)[1]', 'varchar(100)')

但我得到以下错误

XML parsing: line 1, character 537, illegal xml character

原因是AlešHolubec是XML中交易者的名字,我们无法改变。 请帮助解决此问题

2 个答案:

答案 0 :(得分:3)

您可以将字符串转换为nvarchar(max),然后将编码替换为UTF-16来解决此问题。

;WITH XMLNAMESPACES(DEFAULT 'mynamespace')
SELECT CONVERT(XML, replace(cast(column_name as nvarchar(max)), '<?xml version="1.0" encoding="UTF-8"?>', '<?xml version="1.0" encoding="UTF-16"?>')).value ('(APIDATA/TRADE/@Action)[1]', 'varchar(100)')

或者您可以删除XML声明。

;WITH XMLNAMESPACES(DEFAULT 'mynamespace')
SELECT CONVERT(XML, replace(column_name, '<?xml version="1.0" encoding="UTF-8"?>', '')).value ('(APIDATA/TRADE/@Action)[1]', 'varchar(100)')

答案 1 :(得分:1)

我遇到了与特殊字符和XML相同的问题。下面是我为解决您需要为数据库修改的工作代码问题所做的一个示例。

我唯一需要C#来处理的是单引号。 C#需要在将单引号发送为CSV列表之前将其更改为',否则它将失败。

希望这会有所帮助..

/**************************************************************************************
 **************************************************************************************
 ***    
 ***    This is to demonstrate how to use XML in SQL statements.
 ***    C# must send the the list of items in comma seperated values and 
 ***    replace the character Single Quote with &apos; or the SQL statement 
 ***    will fail.  This is the only character that SQL can not handle when sent as a
 ***    string.
 ***    
 ***    The steps below will explain each part and how it handles special 
 ***    characters in XML and turns them into a temp table.
 ***
 ***
 **************************************************************************************
 **************************************************************************************/

SET ARITHABORT ON

DECLARE @CUST_REF3 AS XML 
DECLARE @CSharpString AS NVARCHAR(MAX)

    --This is used for when the CSV string is passed in normally.
SET @CSharpString = ISNULL('{0}', '')
    --Example of when the CSV string is passed in and it having a special characters.
SET @CSharpString = 'SHOP A, LA WHEEL & BRAKE SHOP, SHOP&apos;s B'
    --Example of when nothing is passed in from C#
    --SET @CSharpString = ''

--Replaces any special character for preperation of XML formating
SET @CSharpString = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@CSharpString,'&', '&amp;'),'<', '&lt;'),'>', '&gt;'),'"', '&quot;'),'''', '&apos;')

-- Turn the @CSharpString (CSV) into XML
SET @CUST_REF3 = CAST('<A>'+ NULLIF(REPLACE(@CSharpString, N',', '</A><A>'), '') + '</A>' AS XML)

--Display the converted XML list
SELECT @CUST_REF3

--Converts the XML nodes into a temp table.  Make sure the data type is set correctly for the data being received.
SELECT dbo.Trim(CUST_REF3.value('.','nchar(22)')) AS [CUST_REF3] 
INTO #XML_List
FROM @CUST_REF3.nodes('/A') AS x(CUST_REF3)

--Display what Converted list
SELECT * FROM #XML_List

--example of output from the C# String
SELECT USER_DOC, CUST_REF3 
  FROM dbo.WO_HDR 
 WHERE 
        --This matches the list of items sent from C#
      ((SELECT TOP(1) x.CUST_REF3 
          FROM #XML_List x 
         WHERE x.CUST_REF3 = dbo.WO_HDR.CUST_REF3) IS NOT NULL OR

         --If the user did not select anything, do not filter
         @CSharpString = '')

--Dispose of temp table
IF OBJECT_ID('tempdb..#XML_List') IS NOT NULL                   
DROP TABLE #XML_List

/**********************************************************************************************************************************************************
--Summerized code to use:
        SET ARITHABORT ON
        DECLARE @CUST_REF3 AS XML 
        DECLARE @CSharpString AS NVARCHAR(MAX)

        SET @CSharpString = ISNULL('{0}', '')
        SET @CSharpString = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@CSharpString,'&', '&amp;'),'<', '&lt;'),'>', '&gt;'),'"', '&quot;'),'''', '&apos;')
        SET @CUST_REF3 = CAST('<A>'+ NULLIF(REPLACE(@CSharpString, N',', '</A><A>'), '') + '</A>' AS XML)

        SELECT dbo.Trim(CUST_REF3.value('.','nchar(22)')) AS [CUST_REF3] INTO #XML_List FROM @CUST_REF3.nodes('/A') AS x(CUST_REF3)

        --Add this scring to every WHERE statment you want this filter to be used.
        --((SELECT TOP(1) x.CUST_REF3 FROM #XML_List x WHERE x.CUST_REF3 = dbo.WO_HDR.CUST_REF3) IS NOT NULL OR @CSharpString = '')

        IF OBJECT_ID('tempdb..#XML_List') IS NOT NULL DROP TABLE #XML_List
 **********************************************************************************************************************************************************/