C# 如果字符串以<;开头,则将xml字符串解析为xml文档将失败;?xml&燃气轮机;部分

C# 如果字符串以<;开头,则将xml字符串解析为xml文档将失败;?xml&燃气轮机;部分,c#,.net,xml,C#,.net,Xml,我有一个如下开头的XML文件: <?xml version="1.0" encoding="utf-8"?> <Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition"> <DataSources

我有一个如下开头的XML文件:

<?xml version="1.0" encoding="utf-8"?>
<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition">
  <DataSources>
我得到以下XmlException:

根级别的数据无效。 第1行,位置1

删除版本和编码节点可以解决这个问题。为什么?如何正确处理此xml?

您的xml开头有(BOM)吗?它是否与您的编码匹配?如果你删掉了标题,你也会删掉BOM表,如果这是不正确的,那么后续的解析可能会起作用


您可能需要在字节级别检查文档以查看BOM表

既然文件是xml文件,为什么还要费心将其读取为字节序列,然后将其转换为字符串?只需让框架为您加载并处理编码:

var xml = XDocument.Load("test.xml");

我的第一个想法是,当从.NET字符串类型解析XML时,编码是Unicode。 看起来,尽管XDocument的解析对此相当宽容

这个问题实际上与UTF8前导码/字节顺序标记(BOM)有关,它是UTF-8流开头的一个三字节签名。这三个字节是关于流中使用的编码的提示

您可以通过在类的实例上调用该方法来确定编码的前导。 例如:

// returns { 0xEF, 0xBB, 0xBF }
byte[] preamble = Encoding.UTF8.GetPreamble();
序言应该由
XmlTextReader
正确处理,因此只需从
XmlTextReader
加载
XDocument

XDocument xml;
using (var xmlStream = new MemoryStream(fileContent))
using (var xmlReader = new XmlTextReader(xmlStream))
{
    xml = XDocument.Load(xmlReader);
}

如果只有字节,则可以将字节加载到流中:

XmlDocument oXML;

using (MemoryStream oStream = new MemoryStream(oBytes))
{
  oXML = new XmlDocument();
  oXML.Load(oStream);
}
XDocument oXML;

using (MemoryStream oStream = new MemoryStream(oBytes))
using (XmlTextReader oReader = new XmlTextReader(oStream))
{
  oXML = XDocument.Load(oReader);
}
或者,您可以在加载XML之前将字节转换为字符串(假定您知道编码):

string sXml;
XmlDocument oXml;

sXml = Encoding.UTF8.GetString(oBytes);
oXml = new XmlDocument();
oXml.LoadXml(sXml);
我已经将我的示例显示为与.NET 2.0兼容,如果您使用的是.NET 3.5,则可以使用
XDocument
而不是
XmlDocument

将字节加载到流中:

XmlDocument oXML;

using (MemoryStream oStream = new MemoryStream(oBytes))
{
  oXML = new XmlDocument();
  oXML.Load(oStream);
}
XDocument oXML;

using (MemoryStream oStream = new MemoryStream(oBytes))
using (XmlTextReader oReader = new XmlTextReader(oStream))
{
  oXML = XDocument.Load(oReader);
}
将字节转换为字符串:

string sXml;
XDocument oXml;

sXml = Encoding.UTF8.GetString(oBytes);
oXml = XDocument.Parse(sXml);
试试这个:

int startIndex = xmlString.IndexOf('<');
if (startIndex > 0)
{
    xmlString = xmlString.Remove(0, startIndex);
}

int startIndex=xmlString.IndexOf(“我也遇到了这个错误,因为源XML是一个字符串,它以某种方式获得了一些不可打印的字符,这些字符似乎破坏了
XmlDocument
XDocument
的解析。将它们剥离可以解决这个问题:

string sanitized = Regex.Replace(part, @"\p{C}+", string.Empty);

信用证:

什么是字节顺序标记…?我怎样才能找到文档的编码?我只是怀疑它是utf-8(读文本是可读的)请参阅我发布的链接。它是标题前的一个字节序列,充当文档编码的指令。请注意,UTF-8“pre-amble”是Microsoft的一项发明,与普通的UTF-16 BOM不同,它不受任何Unicode标准的认可。它不应用于书写,尽管您必须在阅读时处理它在野外经常会遇到讨厌的家伙。@bobince-我同意(虽然Unicode标准允许使用它,但不鼓励使用它-有关详细信息,请参阅的第36页).我已经修改了答案-见最后一段。因为我没有从路径获取xml。我只有字节内容,这些字节来自哪里?数据库、网络流等等?问题是我需要使用XDocument@agnieszka-我已经更新了我的答案,让您了解如何使用XDocument.string,如果原始
o字节
包含字节顺序标记序列。我必须调用
sXml=sXml.Substring(1);
否则根级别的错误
数据无效。第1行,位置1。
被抛出
XDocument.Parse
。BOM字节不可见,因此可以使用
.WriteLine(“第一个字符”{0}',sXml[0])进行检查
如果您解释这是为了强制跳过序言/BOM,则会有所帮助。