C# REST API响应中的前导unicode字符导致Xml异常

C# REST API响应中的前导unicode字符导致Xml异常,c#,xml,unicode,C#,Xml,Unicode,当我试图解析来自某个REST API的响应时,我得到一个XmlException说“根级别的数据无效。第1行,位置1”。查看XML看起来不错,但检查第一个字符时,我发现它实际上是一个字符(字符代码65279或0xFEFF) 有什么好的理由让那个角色出现吗?也许我应该在发出请求时设置不同的编码?目前我正在使用编码.UTF8 我考虑过从字符串中删除该字符,或者要求RESTAPI的开发人员修复它,但在执行这些操作之前,我想检查该字符是否存在有效的原因。我不是unicode专家。我应该做些不同的事情吗

当我试图解析来自某个REST API的响应时,我得到一个
XmlException
说“根级别的数据无效。第1行,位置1”。查看XML看起来不错,但检查第一个字符时,我发现它实际上是一个字符(字符代码65279或0xFEFF)

有什么好的理由让那个角色出现吗?也许我应该在发出请求时设置不同的编码?目前我正在使用
编码.UTF8

我考虑过从字符串中删除该字符,或者要求RESTAPI的开发人员修复它,但在执行这些操作之前,我想检查该字符是否存在有效的原因。我不是unicode专家。我应该做些不同的事情吗

编辑:我怀疑可能是这样的(BOM)。所以,问题变成了,我应该特别处理这个角色吗?我尝试了两种方式加载XML,但都引发了相同的异常:

public static User GetUser()
{
    WebClient req = new WebClient();
    req.Encoding = Encoding.UTF8;
    string response = req.DownloadString(url);

    XmlSerializer ser = new XmlSerializer(typeof(User));
    User user = ser.Deserialize(new StringReader(response)) as User;

    XElement xUser = XElement.Parse(response);

    ...

    return user;
}
U+FFEF是一个很好的例子。它位于文档的开头,用于指示字符编码(或者更确切地说,编码的字节顺序,可以是任意一种方式;最具体的是UTF-16)。它在XML文档的开头出现是完全合理的。不推荐将其用作零宽度非中断空间,而支持U+2060

如果字节顺序标记采用不同的编码,例如,如果它是声称为UTF-8的文档中的UTF-8 BOM,则这是不合理的

您是如何加载文档的?也许您在某个地方指定了不适当的编码?如果可能的话,最好让XMLAPI检测编码

编辑:当你把它作为一个字符串下载后,我可以想象这会引起问题。。。假设它是用来检测编码的,你已经知道了。不要将其作为字符串下载-将其作为二进制数据下载(
WebClient.DownloadData
),然后您应该可以解析它了,我相信。但是,您可能仍然不应该使用
XElement.Parse
,因为可能存在文档声明-使用
XDocument.Parse
。如果调用的结果可以直接输入到
XmlSerializer
,我会有点惊讶,但您可以尝试。。。如有必要,将其包装在一个
内存流中。

U+FFEF是一个。它位于文档的开头,用于指示字符编码(或者更确切地说,编码的字节顺序,可以是任意一种方式;最具体的是UTF-16)。它在XML文档的开头出现是完全合理的。不推荐将其用作零宽度非中断空间,而支持U+2060

如果字节顺序标记采用不同的编码,例如,如果它是声称为UTF-8的文档中的UTF-8 BOM,则这是不合理的

您是如何加载文档的?也许您在某个地方指定了不适当的编码?如果可能的话,最好让XMLAPI检测编码


编辑:当你把它作为一个字符串下载后,我可以想象这会引起问题。。。假设它是用来检测编码的,你已经知道了。不要将其作为字符串下载-将其作为二进制数据下载(
WebClient.DownloadData
),然后您应该可以解析它了,我相信。但是,您可能仍然不应该使用
XElement.Parse
,因为可能存在文档声明-使用
XDocument.Parse
。如果调用的结果可以直接输入到
XmlSerializer
,我会有点惊讶,但您可以尝试。。。如有必要,将其包装在
内存流中。

开头的字符是BOM(字节顺序标记)。它作为unicode文本文件中的第一个字符放置,以指定用于创建文件的编码

BOM不应该是响应的一部分,因为HTTP内容的编码方式不同


通常,响应中的BOM来自发送文本文件作为响应,其中文本文件与BOM签名一起保存。例如,Visual Studio有一个选项,可以保存不带BOM签名的文件,以便直接作为响应发送。

开头的字符是BOM(字节顺序标记)。它作为unicode文本文件中的第一个字符放置,以指定用于创建文件的编码

BOM不应该是响应的一部分,因为HTTP内容的编码方式不同


通常,响应中的BOM来自发送文本文件作为响应,其中文本文件与BOM签名一起保存。例如,VisualStudio有一个选项,可以保存一个没有BOM签名的文件,这样就可以直接将其作为响应发送。

这就是所谓的。但在UTF-8中不需要它。

这称为a。但是UTF-8中不需要它。

不要使用编码。UTF8,使用构造函数重载创建自己的UTF-8编码器,该重载允许您指定是否要发出BOM表:

req.Encoding = new UTF8Encoding( false ) ; // omit the BOM
我相信这会对你有好处

修改为注释:以下各项将起作用:


不要使用Encoding.UTF8,而是使用构造函数重载创建自己的UTF-8编码器,该重载允许您指定是否要发出BOM表:

req.Encoding = new UTF8Encoding( false ) ; // omit the BOM
我相信这会对你有好处

修改为注释:以下各项将起作用:


我使用的是
XmlSerializer
XElement.Parse()
。请参阅对我的问题的编辑。我正在使用
XmlSerializer
XElement.Parse()
。请参阅对我的问题的编辑。遗憾的是,这不起作用。我仍然收到一个U+FFEF作为
req.DownloadString()
返回的第一个字符,并且仍然抛出
XmlException
。@gilly3:有关解决方案,请参阅我的修订答案