Подтвердить что ты не робот

Разбор 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?

4b9b3361

Ответ 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);
}