簡體   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