为什么en-dash( – )会触发非法的XML字符错误(C#/ SSMS)?

这不是关于如何克服“ XML解析:…非法xml字符”错误的问题,而是关于它为什么会发生的问题?我知道有修复( 1,2,3),但在选择最佳解决方案之前需要知道问题出在哪里(导致错误的原因是什么?).

我们使用C#调用基于Java的Web服务.从返回的强类型数据中,我们创建了一个将传递给sql Server的XML文件. Web服务数据使用UTF-8进行编码,因此在C#中我们创建文件,并在适当的地方指定UTF-8:

var encodingType = Encoding.UTF8;
// logic removed...
var xdoc = new XDocument();
xdoc.Declaration = new XDeclaration("1.0",encodingType.WebName,"yes");
// logic removed...
System.IO.File.WriteallText(xmlFullPath,xdoc.Declaration.ToString() + xdoc.Document.ToString(),encodingType);

这将在磁盘上创建一个包含以下(缩写)数据的XML文件

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<records>
  <r RecordName="Option - Foo" />
  <r RecordName="Option – Bar" />
</records>

请注意,在第二条记录中,– 与 – 不同.我相信第二个例子是en-dash.

如果我在Firefox / IE / VS2015中打开该XML文件.它打开没有错误. W3C XML validator也可以正常工作.但是,SSMS 2012不喜欢它:

declare @xml XML = '<?xml version="1.0" encoding="utf-8" standalone="yes"?><records>
  <r RecordName="Option - Foo" />
  <r RecordName="Option – Bar" />
</records>';

XML parsing: line 3,character 25,illegal xml character

那么为什么en-dash会导致错误呢?从我的研究来看,似乎是这样

…only a few entities that need escaping: <,>,\,’ and & in both HTML and
XML.
07005

…其中en-dash不是一个.编码版本(替换 – 和&#8211;)工作正常.

UPDATE

根据输入,人们声明en-dash不被识别为UTF-8,但它在此处列出http://www.fileformat.info/info/unicode/char/2013/index.htm
那么,作为一个完全合法的角色,为什么SSMS在以XML格式传递时不会读取它(使用UTF-8或UTF-16)?

你能修改XML编码声明吗?如果是这样;
declare @xml XML = N'<?xml version="1.0" encoding="utf-16" standalone="yes"?><records>
  <r RecordName="Option - Foo" />
  <r RecordName="Option – Bar" />
</records>';

select @xml

(No column name)
<records><r RecordName="Option - Foo" /><r RecordName="Option – Bar" /></records>

推测编辑

这两个都失败了非法的xml字符:

set @xml = '<?xml version="1.0" encoding="utf-8"?><x> – </x>'
set @xml = '<?xml version="1.0" encoding="utf-16"?><x> – </x>'

因为它们将非unicode varchar传递给XML解析器;字符串包含Unicode,因此必须这样处理,即作为nvarchar(utf-16)(否则包含 – 的3个字节被误解为多个字符,并且一个或多个不在XML的可接受范围内)

这会将nvarchar字符串传递给解析器,
但由于无法切换编码而失败:

set @xml = N'<?xml version="1.0" encoding="utf-8"?><x> – </x>'

这是因为nvarchar(utf-16)字符串被传递给XML解析器,但XML文档声明它的utf-8并且 – 在两种编码中不相同

这一切都有效,因为一切都是utf-16

set @xml = N'<?xml version="1.0" encoding="utf-16"?><x> – </x>'

相关文章

php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念