SQL Insert上的非法xml字符

时间:2013-04-14 03:31:53

标签: sql-server coldfusion xml-parsing coldfusion-9

我正在尝试将以下字符串插入到sql xml字段

<?xml version="1.0" encoding="UTF-8"?>
<Response> 
    <Ip>x.x.x.x</Ip>
    <CountryCode>CA</CountryCode> 
    <CountryName>Canada</CountryName>
    <RegionCode>QC</RegionCode> 
    <RegionName>Québec</RegionName> 
    <City>Dorval</City> 
    <ZipCode>h9p1j3</ZipCode> 
    <Latitude>45.45000076293945</Latitude> 
    <Longitude>-73.75</Longitude> 
    <MetroCode></MetroCode> 
    <AreaCode></AreaCode> 
</Response>

插入代码如下:

INSERT 
    INTO Traffic(... , xmlGeoLocation, ...)
    VALUES (
        ...
        <!--- 
        <cfqueryparam CFSQLType="cf_sql_varchar" value="#xmlGeoLocation#">, 
        --->
        '#xmlGeoLocation#',

        ...
        )

发生了两件坏事:

  1. Québec变成Québec

  2. 我收到错误消息[Macromedia][SQLServer JDBC Driver][SQLServer]XML parsing: line 8, character 16, illegal xml character

  3. 更新:

    传入的测试流主要是单字节字符。

    é是一个双字节字符。特别是C3A9

    此外,我无法控制传入的xml流

3 个答案:

答案 0 :(得分:13)

我要剥去标题......

我遇到了一个有趣的小撇号问题。我认为问题在于,当字符串转换为XML时,它不再是UTF-8,但sql server正在尝试使用标头对其进行解码。如果它是VARCHAR,则它是客户端的编码。如果它是NVARCHAR,它是UTF-16。以下是我测试的一些变化:

SQL(varchar,UTF-8):

SELECT CONVERT(XML,'<?xml version="1.0" encoding="UTF-8"?><t>We’re sorry</t>')

错误:

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

SQL(nvarchar,UTF-8):

SELECT CONVERT(XML,N'<?xml version="1.0" encoding="UTF-8"?><t>We’re sorry</t>')

错误:     XML解析:第1行,第38个字符,无法切换编码

SQL(varchar,UTF-16)

SELECT CONVERT(XML,'<?xml version="1.0" encoding="UTF-16"?><t>We’re sorry</t>')

错误:

XML parsing: line 1, character 39, unable to switch the encoding

SQL(nvarchar,UTF-16)

SELECT CONVERT(XML,N'<?xml version="1.0" encoding="UTF-16"?><t>We’re sorry</t>')

工作!

答案 1 :(得分:1)

尝试改变这一点:

<RegionName>Québec</RegionName> 

为:

<RegionName><![CDATA[Québec
]]></RegionName> 

答案 2 :(得分:1)

从w3看一下这个link,它告诉我:

  

在HTML中,有一些内置字符名称的列表,例如&eacute;,但是XML没有这个。在XML中,只有五个内置字符实体:&lt;&gt;&amp;&quot;&apos; for&lt;,&gt;,&amp; ;,“和”。您可以在文档类型定义中定义自己的实体,也可以使用任何Unicode字符(请参阅下一项)。

     

在HTML中,还有数字字符引用,例如&#38;用于&amp ;.您可以引用任何Unicode字符,但数字是十进制,而在Unicode表中,数字通常是十六进制。 XML还允许使用十六进制引用:例如&#x26;

这让我相信,&#xE9;可能适用于é角色。

此Microsoft的link信息表明:

  

SQLXML 4.0依赖于对SQL Server中提供的DTD的有限支持。 SQL Server允许在xml数据类型数据中使用内部DTD,该数据可用于提供默认值并将实体引用替换为其扩展内容。 SQLXML“按原样”(包括内部DTD)将XML数据传递给服务器。您可以使用第三方工具将DTD转换为XML Schema(XSD)文档,并使用内联XSD架构将数据加载到数据库中。

但如果您无法控制传入的XML流,那么所有这些都无济于事。我怀疑是否可以将XML文档中的é(或任何特殊字符,除了上面提到的内置字符实体)保存到SQL Server XML字段中,而无需添加DTD或替换字符它的十六进制参考对应物。在这两种情况下,您都需要能够在进入数据库之前修改XML。

对于任何想要沿着“添加D​​TD”路线的人来说,这只是一个简单的例子。

以下是如何将内部DTD添加到xml文件中,该文件声明了é字符的实体:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY eacute "&#233;">]>
<root>
  <RegionName>Qu&eacute;bec</RegionName>
</root>

如果您转到here并在“Ctrl + F”页面上搜索“eacute”,则最终会出现一个列表,其中包含您可以复制并粘贴到您自己的内部DTD中的其他字符的示例。

修改

您可以在上面的link <!ENTITY eacute "&#233;"><!ENTITY .. // Next entity>处指定添加所有实体,或者只是从file复制所有实体。我确实理解如何将内部DTD添加到添加到数据库的每个XML文件中并不是一个好主意。我很想知道是否为1个文件添加它可以解决您的问题。