繁体   English   中英

将 xml 字符串解析为 xml 文档失败,如果字符串以<?xml… ?>部分

[英]Parsing xml string to an xml document fails if the string begins with <?xml… ?> section

我有一个像这样开头的 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?

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

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

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

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

或者您可以在加载 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);

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

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

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

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

尝试这个:

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

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

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

信用: C# regex 删除不可打印的字符和控制字符,在混合了许多不同语言的文本中,unicode 字母

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM