2

我有一个 SQL 表,它有一个 varchar(8) 列,其中偶尔有二进制数据。(0x01、0x02 等...)。(更改列的格式或内容不是一种选择。)

当我进入 SQL Server 2005 Management Studio 并运行查询时:

select * 
 from mytable 
 where clientID = 431620
 for xml auto

我得到有用的结果。注意 proc_counts 是如何编码的:

<mytable clientID="431620" recno="19014235" pdate="2008-03-04T00:00:00"
   proc_counts="&#x1;&#x1;&#x2;&#x1;" otherstuff="foobar" 
   date="2008-02-17T00:00:00"/>

完全有效的 XML,AFAIK。现在,当我实际编写 C# 代码来读取这一行时,我在 ReadOuterXml 期间抛出异常:

SqlCommand cmd = new SqlCommand("select * from testing xml auto", connection);
using (XmlReader xrd = cmd.ExecuteXmlReader())
{
    xrd.Read();
    while (xrd.ReadState != ReadState.EndOfFile)
    {
        string s = xrd.ReadOuterXml();
        records.Add(s);
    }
}

这抛出:XmlException 未处理。'',十六进制值 0x01 是无效字符。我想要上面的 XML,但没有足够的 Google-fu 来弄清楚为什么我没有得到它。建议?


要使用此类数据创建表,此 Transact SQL 代码在 SSMS 中工作:

create table testing
(clientid int, proc_counts varchar(8));
insert into testing values (1, 'normal');
insert into testing values (2, char(65) + char(1) + char(65));
select * from testing for xml auto;

更新:验尸和解决方法

Dommer 可能是对的,这是给我带来问题的Normalization财产。XmlTextReader问题是(正如您从评论中看到的那样)我发现几乎不可能从 a(SqlCommand).ExecuteXmlReader()转到任何可以让我靠近Normalizationan 属性的东西XmlTextReader。通常,Microsoft 关于此的文档是矛盾的,或者完全是错误的。

所以我决定了一个解决方法。如果我只是使用 anSqlDataReader来吸收输出,一切都很好。XML 看起来很完美,解析也很好。

StringBuilder sb = new StringBuilder();
using(SqlDataReader dr = cmd.ExecuteReader())
{
    while(rdr.Read())
        sb.Append((string)rdr[0]);
}
4

2 回答 2

4

这与 XmlTextReader.Normalization 属性有关。当您显式创建 XmlTextReader 时,此属性设置为 false,因此会解码“无效”字符。当隐式创建 XmlTextReader 时,Normalization 设置为 true。

此处讨论该属性:

http://msdn.microsoft.com/en-us/library/system.xml.xmltextreader.normalization.aspx

如果您“手动”进行处理 - 即创建一个 XmlTextReader - 我认为您将避免该错误。

更新:

框架的最新版本中的更改意味着“XmlReaderSettings.CheckCharacters = false”可能是 ASP.NET 2.0+ 中的方式。可以将 XmlReaderSettings 对象传递给 XmlReader.Create。

于 2009-03-23T19:07:48.260 回答
1

例外是告诉你真相。SQL Server 显然允许显示无效的 XML。试试这个:

select *  from mytable  where clientID = 431620 for xml auto, BINARY BASE64
于 2009-03-23T18:46:11.557 回答