SQL 表上的 XML 读取器返回无效 XML

Cli*_*rce 2 c# xml sql sql-server xmlreader

我有一个 SQL 表,其中有一个 varchar(8) 列,其中偶尔包含二进制数据。(0x01、0x02 等)。(无法更改列的格式或内容。)

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

select * 
 from mytable 
 where clientID = 431620
 for xml auto
Run Code Online (Sandbox Code Playgroud)

我得到了有用的结果。注意 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"/>
Run Code Online (Sandbox Code Playgroud)

完全有效的 XML,据我所知。现在,当我实际编写 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


要创建包含此类数据的表,可以在 SSMS 中使用以下 Transact SQL 代码:

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;
Run Code Online (Sandbox Code Playgroud)

更新:事后分析和解决方法

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

所以我决定采取一种解决方法。如果我只是使用 anSqlDataReader来吸收输出,一切都很好。XML 看起来很完美并且解析得非常好。

StringBuilder sb = new StringBuilder();
using(SqlDataReader dr = cmd.ExecuteReader())
{
    while(rdr.Read())
        sb.Append((string)rdr[0]);
}
Run Code Online (Sandbox Code Playgroud)

dom*_*mer 5

它与 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。