在.NET中过滤非法的XML字符

6
我在MS SQL 2005中有一个XML存储过程,我使用SqlCommand.ExecuteXmlReader获取XmlReader,然后解析数据并形成XML文档。问题是SQL中的数据包含一些二进制字符,在UTF-8 XML文档中是非法的,因此会抛出异常。
有其他人处理过这个问题吗?我考虑在输入到数据库时过滤数据,但那样我就必须在各处放置过滤器,并且每个字符都需要检查。
还有其他建议吗?
编辑: 数据通常存储在不同长度的varchar列中。实际上,数据是从web表单(ASP.NET应用程序)上的用户输入的。因此,有时他们从MS Word等复制粘贴,这会导致出现奇怪的二进制字符。
5个回答

1

我曾经看到过DotNet SqlClient从数据库中的nvarchar列“混淆”数据,我们的理论是这与“代理代码点”有关,参见:

http://www.siao2.com/2005/07/27/444101.aspx

http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=rzaaxsurrogate.htm

http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/c0004816.htm

SqlClient 似乎“解释”了一些字节,导致我们的 Xml 不再是格式良好的,转换为 nvarchar(max) 可以阻止这种情况发生(尽管这会对性能产生影响):

SELECT CONVERT(NVARCHAR(MAX), MyValue) FROM ...

请注意,您需要使用NVARCHAR(MAX),而不是NVARCHAR(N)。
我们还发现OleDB提供程序也可以正常工作(尽管比SqlClient慢)。

0
你的存储过程如何生成XML?如果你在SQL Server中使用任何FOR XML选项,文本字段中的二进制字符将被正确转义。
CREATE TABLE test (
   id int identity(1,1) not null primary key, 
   data nvarchar(50))
INSERT INTO test (data) values (char(0))
SELECT * FROM test FOR XML RAW

产生:

<row ID="1" data="&#x0;" />

我正在使用 "For Xml Explicit"。 - Brandon Montgomery
这不应该成为问题;FOR XML EXPLICIT 也会正确转义二进制 XML 字符。 - Robert Rossney

0
坏数据是如何进入数据库的?您正在使用 XML 列吗?
您可以将过滤器(实际上称为“验证”)放入用于输入数据到数据库中的存储过程中,或者您可以添加触发器来检查数据,无论数据来自何处。
一般来说,不要让坏数据进入数据库!

数据是用户输入,存储在数据库的varchar列中。 - Brandon Montgomery

0

这是编码的问题吗?还是xml格式不正确?如果是格式不正确,我无能为力。但对于编码...很遗憾ExecuteXmlReader不允许您指定编码,但您可以将数据视为BLOB,并使用自己的编码和XmlReader单独处理它。

如果数据很大,您可能需要使用ExecuteReaderCommandBehavior.SequentialAccess,并将其写入临时文件(Path.GetTempFileName())-然后将该文件作为StreamXmlReader一起处理。


0

我已经在应用程序中的各个地方抽象了创建SqlParameter对象的过程,因此我将在那一点上清理输入。我的抽象方法创建并返回一个SqlParameter对象,用于调用存储过程。如果调用者想要一个varchar类型的参数,我将循环遍历他们想要转换为SqlParameter对象的字符串的每个字符,并过滤掉那些非法的二进制XML字符。这将消除不良数据首次进入数据库的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接