Разбор xml-строки в XML-документе завершается с ошибкой, если строка начинается с раздела <? 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.
Вырезание версии и кодировки node устраняет проблему. Зачем? Как правильно обработать этот xml?
Ответы
Ответ 1
Если у вас есть только байты, вы можете либо загрузить байты в поток:
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
Моя первая мысль заключалась в том, что кодировка является Unicode при анализе XML из строкового типа .NET.
Кажется, однако, что синтаксический анализ XDocument довольно прост по отношению к этому.
Проблема на самом деле связана с отметкой порядка преамбулы/байта UTF8 (BOM), которая представляет собой трехбайтную подпись необязательно присутствующую в начало потока UTF-8. Эти три байта являются подсказкой относительно используемой в потоке кодировки.
Вы можете определить преамбулу кодирования, вызвав метод 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);
}
Ответ 3
Почему нужно читать файл в виде последовательности байтов, а затем преобразовывать его в строку, пока это xml файл? Просто оставьте рамку загружать для вас и справиться с кодировками:
var xml = XDocument.Load("test.xml");
Ответ 4
У вас есть byte-order-mark (BOM) в начале вашего XML и соответствует ли это вашей кодировке? Если вы отрубите свой заголовок, вы также измельчите спецификацию, и если это неверно, последующий синтаксический анализ может работать.
Вам может потребоваться проверить ваш документ на уровне байта, чтобы просмотреть спецификацию.
Ответ 5
Попробуйте следующее:
int startIndex = xmlString.IndexOf('<');
if (startIndex > 0)
{
xmlString = xmlString.Remove(0, startIndex);
}