如果字符串以<! - ?xml ...? - >部分开头,则将xml字符串解析为xml文档会失败

时间:2010-01-21 17:57:22

标签: 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>

当我运行以下代码时:

byte[] fileContent = //gets bytes
            string stringContent = Encoding.UTF8.GetString(fileContent);
            XDocument xml = XDocument.Parse(stringContent);

我得到以下XmlException:

  

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

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

6 个答案:

答案 0 :(得分:23)

我首先想到的是,从.NET字符串类型解析XML时,编码是Unicode。 看来,虽然XDocument的解析对此非常宽容。

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

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

// returns { 0xEF, 0xBB, 0xBF }
byte[] preamble = Encoding.UTF8.GetPreamble();

前言应由XmlTextReader正确处理,因此只需从XDocument加载XmlTextReader

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

答案 1 :(得分:17)

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

XmlDocument oXML;

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

或者您可以在加载XML之前将字节转换为字符串(假设您知道编码):

string sXml;
XmlDocument oXml;

sXml = Encoding.UTF8.GetString(oBytes);
oXml = new XmlDocument();
oXml.LoadXml(sXml);

我已经将我的示例显示为与.NET 2.0兼容,如果您使用的是.NET 3.5,则可以使用XDocument而不是XmlDocument

将字节加载到流中:

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);

答案 2 :(得分:8)

为什么要打扰将文件作为字节序列读取,然后在xml文件中将其转换为字符串?只需让框架为您加载并处理编码:

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

答案 3 :(得分:6)

您的XML开头是否有byte-order-mark(BOM),是否与您的编码匹配?如果你砍掉你的标题,你也会砍掉BOM,如果这不正确,那么随后的解析可能会有效。

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

答案 4 :(得分:2)

试试这个:

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

答案 5 :(得分:0)

我也遇到过这个错误,因为源 XML 是一个字符串,它以某种方式获得了一些似乎破坏 XmlDocumentXDocument 解析的不可打印字符。剥离它们解决了问题:

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

信用:C# regex to remove non - printable characters, and control characters, in a text that has a mix of many different languages, unicode letters