xml.LoadData - Недійсні дані на кореневому рівні. Рядок 1, позиція 1


79

Я намагаюся проаналізувати якийсь XML у програмі встановлення WiX. XML буде об'єктом усіх моїх помилок, повернутих з веб-сервера. Я отримую помилку в назві питання з цим кодом:

XmlDocument xml = new XmlDocument();
try
{
    xml.LoadXml(myString);
}
catch (Exception ex)
{
    System.IO.File.WriteAllText(@"C:\text.txt", myString + "\r\n\r\n" + ex.Message);
    throw ex;
}

myStringце (як видно з результату text.txt)

<?xml version="1.0" encoding="utf-8"?>
<Errors></Errors>

text.txt виходить виглядати так:

<?xml version="1.0" encoding="utf-8"?>
<Errors></Errors>

Data at the root level is invalid. Line 1, position 1.

Мені потрібен цей XML для синтаксичного аналізу, щоб я міг перевірити, чи не мали я помилок.

Редагувати

Це питання не є копією, як позначено. У цьому питанні особа, яка задала запитання, використовувала LoadXmlдля синтаксичного аналізу XML-файл. Я аналізую рядок, що є правильним використаннямLoadXml


Насправді потрібно було б побачити xml, щоб допомогти
RedEyedMonster

Я додав його до запитання, але це вже було в результатах text.txt.
Кріс

1
@JohnSaunders - Це не дублікат цього питання. У цьому питанні той, хто задавав запитання, використовував LoadXml для синтаксичного аналізу XML-файлу. Я аналізую рядок, що є правильним використанням LoadXml.
Кріс

1
@marc_s: чи stringсправді коли-небудь може бути UTF-8? Що робити, якщо інструкція з обробки (перший рядок) буде видалена перед завантаженням?
Джон Сондерс,

2
Якщо я беру ваш код і компілюю та запускаю його, я не отримую помилок. Але це, можливо, тому, що я заповнюю свою строку жорстко закодованою. Як встановлюється ваш myString? Якщо це надходить з іншого файлу або потоку, може бути щось дратує, як позначка байтового замовлення у верхній частині файлу. Зазвичай його не показують редактори (якщо у них немає шестигранного режиму).
Річард

Відповіді:


121

Прихований персонаж - це, мабуть, BOM. Пояснення проблеми та її рішення можна знайти тут , а саме Джеймса Шуберта, на основі відповіді Джеймса Бранкіна, яка знаходиться тут .

Хоча попередня відповідь видаляє прихований символ, вона також видаляє весь перший рядок. Більш точна версія буде такою:

string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (xml.StartsWith(_byteOrderMarkUtf8))
{
    xml = xml.Remove(0, _byteOrderMarkUtf8.Length);
}

Я зіткнувся з цією проблемою під час отримання файлу XSLT із BLOB-об'єкта Azure та завантаження його в об'єкт XslCompiledTransform. На моїй машині файл виглядав чудово, але після завантаження його як великої крапки та повернення назад було додано символ специфікації.


3
Не впевнений, і, мабуть, мені доведеться продовжувати шукати, але коли я це зроблю _byteOrderMarkUtf8 = "". так це не ловить. Ідеї?
user1040975

1
спробував, не допомогло. xml з цього приводу йде з db
Джон Деметріу,

1
Encoding.UTF8.GetString (Encoding.UTF8.GetPreamble ()) обчислює порожній рядок
Містер Кук

6
Мав ті самі проблеми, що і вищевказані коментатори. Використання xmlStartsWith(byteOrderMarkUtf8, StringComparison.Ordinal)зробило для мене фокус. Кредит Hans Passant: stackoverflow.com/a/19495964/38425
Polshgiant

2
Це вирішило проблему для мене, ВЕЛИЧЕЗНЕ дякую, я вже деякий час вдарився цим.
mknopf

63

Load()Замість цього використовуйте метод, який вирішить проблему. Побачити більше


16
Я використовую XDocument.Load (), і у мене проблема.
Б. Клей Шеннон,

1
Здається, XmlDocument.Load () піклується про кодування файлів, коли це, відповідно, вказано в заголовку. Якщо ні, можливо, доведеться мати справу з StreamReader та XmlDocument.LoadXml та іншими інструментами.
CLS

Це було моє виправлення у 2020 році
MX313,

15

Проблема тут полягала в тому, що myStringбув цей рядок заголовка. Або на початку першого рядка був якийсь прихований символ, або сам рядок спричиняв помилку. Я відрізав перший рядок так:

xml.LoadXml(myString.Substring(myString.IndexOf(Environment.NewLine)));

Це вирішило мою проблему.


4
Одного разу я отримав цю помилку, і вона виявилася знаком "?" на початку. Я просто замінив його на порожній пробіл і запустив його ... Це також може статися, якщо файл, який ви читаєте, має інше кодування, ніж те, що ви очікуєте
Рікардо Епплтон,

Я спробував це, але в .NETPrehistoric (1.1) я спробував використовувати "\ r \ n" замість тоді недоступного Environment.NewLine. Я зрозумів, "Вказаний аргумент вийшов за межі дійсних значень".
Б. Клей Шеннон,

@Chris: Я спробував ваше рішення. Я потрапляю нижче винятку. System.ArgumentOutOfRangeException: StartIndex не може бути менше нуля. Параметр
Шеша

10

Я думаю, що проблема полягає в кодуванні. Ось чому видалення першого рядка (з байтом кодування) може вирішити проблему.

Моє рішення для даних на кореневому рівні недійсне. Рядок 1, позиція 1. in XDocument.Parse(xmlString)замінював його наXDocument.Load( new MemoryStream( xmlContentInBytes ) );

Я помітив, що мій рядок xml виглядав нормально:

<?xml version="1.0" encoding="utf-8"?>

але в іншому кодуванні текстового редактора це виглядало так:

?<?xml version="1.0" encoding="utf-8"?>

Наприкінці мені знадобився не рядок xml, а байт xml []. Якщо вам потрібно використовувати рядок, ви повинні шукати "невидимі" байти у своєму рядку і грати з кодуваннями, щоб налаштувати вміст xml для синтаксичного аналізу або завантаження.

Сподіваюся, це допоможе


3

Я вирішив цю проблему безпосереднім редагуванням байтового масиву. Зберіть преамбулу UTF8 і видаліть безпосередньо заголовок. Після цього ви можете перетворити байт [] у рядок за допомогою методу GetString, див. Нижче. \ R і \ t я також видалив, просто з обережності.

XmlDocument configurationXML = new XmlDocument();
List<byte> byteArray = new List<byte>(webRequest.downloadHandler.data);

foreach(byte singleByte in Encoding.UTF8.GetPreamble())
{
     byteArray.RemoveAt(byteArray.IndexOf(singleByte));
}
string xml = System.Text.Encoding.UTF8.GetString(byteArray.ToArray());
       xml = xml.Replace("\\r", "");
       xml = xml.Replace("\\t", "");

Це працює для мене. Але в циклі нам потрібно перевірити byteArray.IndexOf (singleByte)! = -1 чи ні, перш ніж видалити його.
ThanhLD

2

Збережіть файл з іншим кодуванням:

Файл> Зберегти файл як ...> Зберегти як UTF-8 без підпису.

У VS 2017 ви знайдете кодування як спадне меню поруч із кнопкою Зберегти.


2

Спочатку у мене були проблеми з уникненням символу "&", потім діакритичні знаки та спеціальні літери були показані як знаки запитання, і в кінцевому підсумку згадана проблема виникла.

Я подивився на відповіді і використав пропозицію @ Рінго, щоб спробувати метод Load () як альтернативу. Це змусило мене зрозуміти, що я можу впоратися зі своєю реакцією іншими способами, не просто як рядок.

використання System.IO.Stream замість рядка вирішило всі проблеми для мене.

var response = await this.httpClient.GetAsync(url);
var responseStream = await response.Content.ReadAsStreamAsync();
var xmlDocument = new XmlDocument();
xmlDocument.Load(responseStream);

Найцікавіше у Load () полягає в тому, що цей метод автоматично виявляє формат рядків вхідного XML (наприклад, UTF-8, ANSI тощо). Побачити більше


1

Якщо ваш xml знаходиться в рядку, використовуйте наступне, щоб видалити будь-яку позначку порядку байтів:

        xml = new Regex("\\<\\?xml.*\\?>").Replace(xml, "");

Дійсно врятував мені життя. Я спробував усі пропозиції, але ваше рішення вирішило мою проблему. Дуже дякую!
Торніке Гомарелі

0

Я знайшов одне із рішень. Для вашого коду це може бути наступним чином -

XmlDocument xml = new XmlDocument();
try
{
    // assuming the location of the file is in the current directory 
    // assuming the file name be loadData.xml
    string myString = "./loadData.xml";
    xml.Load(myString);
}
catch (Exception ex)
{
    System.IO.File.WriteAllText(@"C:\text.txt", myString + "\r\n\r\n" + ex.Message);
    throw ex;
}

Це рішення, але погане. Це проблема кодування. Записуючи та читаючи файл, ви фактично виконували кодування та декодування, не знаючи про це, оскільки викликане перевантаження методу Load має значення за замовчуванням для параметра Encoding (кодування
System.Text.Encoding

дякую, сер, що вказали на це, не могли б ви виправити мене?
Shubhasish Bhunia

Вам слід декодувати та кодувати рядок, використовуючи методи класу Encoding, немає потреби (і сенсу) взагалі використовувати файлові методи або файлову систему. Будь ласка, перевірте: docs.microsoft.com/en-us/dotnet/api/…
hardyVeles

0

якщо ми використовуємо XDocument.Parse (@ ""). Використовуйте @, щоб вирішити проблему.


0

Основною виною цієї помилки є логіка, яка визначає кодування при перетворенні Streamабо byte[]масиві в .NET string.

Використання StreamReaderствореного з параметром 2-го конструктора detectEncodingFromByteOrderMarksзначення true, визначить правильне кодування та створення, stringяке не порушує XmlDocument.LoadXmlметод.

public string GetXmlString(string url)
{
    using var stream = GetResponseStream(url);
    using var reader = new StreamReader(stream, true);
    return reader.ReadToEnd(); // no exception on `LoadXml`
}

Поширеною помилкою було б просто наосліп використовувати UTF8кодування на streamабо byte[]. Нижче наведений код створить stringтакий вигляд, який виглядає дійсним при перевірці у відладчику Visual Studio або кудись вставці, але він створить виняток при використанні Loadабо LoadXmlякщо файл кодується інакше, ніж UTF8 без BOM.

public string GetXmlString(string url)
{
    byte[] bytes = GetResponseByteArray(url);
    return System.Text.Encoding.UTF8.GetString(bytes); // potentially exception on `LoadXml`
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.