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

agn*_*zka 27 .net c# 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>
Run Code Online (Sandbox Code Playgroud)

当我运行以下代码时:

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

我得到以下XmlException:

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

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

Dav*_*ray 25

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

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

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

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

前言应该正确处理XmlTextReader,所以只需加载你XDocumentXmlTextReader:

XDocument xml;
using (var xmlStream = new MemoryStream(fileContent))
using (var xmlReader = new XmlTextReader(xmlStream))
{
    xml = XDocument.Load(xmlReader);
}
Run Code Online (Sandbox Code Playgroud)


ste*_*ell 17

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

XmlDocument oXML;

using (MemoryStream oStream = new MemoryStream(oBytes))
{
  oXML = new XmlDocument();
  oXML.Load(oStream);
}
Run Code Online (Sandbox Code Playgroud)

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

string sXml;
XmlDocument oXml;

sXml = Encoding.UTF8.GetString(oBytes);
oXml = new XmlDocument();
oXml.LoadXml(sXml);
Run Code Online (Sandbox Code Playgroud)

我已经将我的示例显示为与.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);
}
Run Code Online (Sandbox Code Playgroud)

将字节转换为字符串:

string sXml;
XDocument oXml;

sXml = Encoding.UTF8.GetString(oBytes);
oXml = XDocument.Parse(sXml);
Run Code Online (Sandbox Code Playgroud)


Dar*_*rov 8

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

var xml = XDocument.Load("test.xml");
Run Code Online (Sandbox Code Playgroud)

  • 因为我没有从路径中获取xml.我只有字节内容 (2认同)

Bri*_*new 7

您是否在XML的开头有一个字节顺序标记(BOM),它是否与您的编码匹配?如果你砍掉你的标题,你也会砍掉BOM,如果这不正确,那么随后的解析可能会有效.

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