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

Исправление плохого файла XML (например, unescaped и т.д.)

У меня есть XML файл от третьей стороны, который я должен импортировать в свое приложение, а в XML есть элементы с неоткрытым и внутренним текстом, и они не хотят исправлять это! Итак, мой вопрос - лучший способ справиться с этой проблемой?

Этот XML довольно большой, и это исправление должно быть быстрым, мое первое решение - просто замена и символ амперсандом, но на самом деле мне не нравится это "решение" по очевидным причинам. Я не знаю, как использовать XmlStringReader с таким XML, потому что это исключение для таких строк, поэтому я не могу использовать HtmlEncode во внутреннем тексте. Я попытался установить XmlTextReader Settings.CheckCharacters в false, но без результата.

Вот пример и находится в элементе, и в этом поле может быть любое, что может быть в каком-то названии компании, поэтому мое исправление замены, возможно, не работает для какого-либо другого названия компании, я хотел бы как-то использовать HtmlEncode, но только по внутреннему тексту, конечно.

<komitent ID="001398">
  <sifra>001398</sifra>
  <redni_broj>001398</redni_broj>
  <naziv>LJUBICA & ŽARKO</naziv>
  <adresa1>Odvrtnica 27</adresa1>
  <adresa2></adresa2>
  <drzava>HRVATSKA</drzava>
  <grad>Zagreb</grad>
</komitent>
4b9b3361

Ответ 1

Ключевое сообщение, приведенное ниже, состоит в том, что, если вы не знаете точный формат входного файла и не гарантируете, что любое отклонение от XML будет согласованным, вы не можете программно исправить, не рискуя, что ваши исправления будут неверными.

Исправление, заменяя & на &amp;, является приемлемым решением тогда и только тогда, когда:

  • Не существует приемлемого корректного источника данных.

    • Как комментирует @Darin Dimitrov, попробуйте найти лучшего поставщика или попросите этого провайдера исправить его.
    • JSON (например) предпочтительнее плохо сформированного XML, даже если вы не используете javascript.
  • Это одноразовый (или, по крайней мере, крайне редкий) импорт.

    • Если вам нужно получить это во время выполнения, то это решение не будет работать.
  • Вы можете продолжать повторять, разрабатывая новые исправления для него, добавляя решение каждой проблемы, когда вы сталкиваетесь с ней.

    • Вероятно, вы обнаружите, что после того, как вы "зафиксировали" его, экранируя символы &, будут другие ошибки.
  • У вас есть ресурсы для проверки целостности "фиксированных" данных вручную.

    • Ошибки, которые вы исправляете, могут быть более тонкими, чем вы понимаете.
  • В документе нет правильно отформатированных объектов -

    • Просто замена & на &amp; приведет к ошибочному изменению &quot; на &amp;quot;. Вы можете обойти это, но не быть наивным о том, насколько сложно это может быть (сущности могут быть определены в DTD, могут ссылаться на кодовую точку юникода...)

    • Если это конкретный элемент, который неверно работает, вы можете рассмотреть возможность добавления содержимого элемента с помощью <![CDATA ]]>, но все еще полагается на то, что вы можете надежно найти начальный и конечный теги.

Ответ 2

Начните с изменения своего мышления. Вход не XML, поэтому не называйте его XML. Даже не используйте "xml", чтобы пометить ваши вопросы об этом. Тот факт, что это не XML, означает, что вы не можете использовать с ним какие-либо инструменты XML, и вы не можете получить какие-либо преимущества обмена данными XML. Вы имеете дело с проприетарным форматом, который поставляется без спецификации и без каких-либо инструментов. Относитесь к нему так же, как и к другому проприетарному формату - попробуйте найти спецификацию того, что вы получаете, и напишите для него парсер.

Ответ 3

Если вы знаете теги файла и хотите "хорошо" текст внутри тегов, которые могут иметь подозрительные данные, вы можете сделать что-то вроде этого:

private static string FixBadXmlText(string xmlText)
{           
    var unreliableTextTags = new[] { "message", "otherdata", "stacktrace", "innerexception" };

    foreach(var tag in unreliableTextTags)
    {
        string openTag = "<" + tag + ">";
        string closeTag = "</" + tag + ">";
        xmlText = xmlText.Replace(openTag, openTag + "<![CDATA[").Replace(closeTag, "]]>" + closeTag);
    }

    return xmlText;
}

Все, что находится внутри раздел CDATA (<![CDATA[ {your text here} ]]>), не будет интерпретироваться синтаксическим анализатором XML, необходимо избегать. Это помогло мне, когда захотелось разобрать плохо написанный XML, который не смог должным образом избежать ввода.

Ответ 4

Поскольку ваш исходный XML ошибочен, вы не можете использовать XmlReaders, потому что они не могут его правильно прочитать.

Если только значения узлов XML не являются htmlEncoded, вам придется идти и вручную читать строку, анализировать (получать имя xml node и его значение), кодировать и выводить в новый файл.

Часто мы оказываемся в подобной ситуации, поэтому я понимаю ваши боли - большую часть времени, хотя ошибки имеют некоторое "правило", поэтому я предполагаю, что они не кодировали название бизнеса (и, возможно, название улицы), поэтому вы можете просто искать эту строку <naziv>, а закрывающий тег </naziv> и HtmlEncode все между ними. Кроме того, поскольку это название компании, у него не будет разрывов строк, что может немного облегчить вам жизнь...

Ответ 5

Вы можете попробовать что-то с регулярными выражениями в зависимости от того, насколько сложна структура:

Regex mainSplitter = new Regex("<komitent ID=\"([0-9]*)\">(.*?)</komitent>");
Regex nazivFinder = new Regex("<naziv>(.*?)</naziv>");

foreach (Match item in mainSplitter.Matches(test))
{
    Console.WriteLine(item);

    string naziv = null;

    Match node = nazivFinder.Match(item.Groups[2].Value);
    if (node != null)
        naziv = node.Groups[1].Value;
}

Ответ 6

Вы можете обрабатывать файл как XPL и даже использовать парсер XPL для преобразования таких файлов в допустимый XML. XPL (eXtensible Process Language) аналогичен XML, но парсер позволяет использовать "специальные символы" XML в текстовых полях. Таким образом, вы можете запустить недопустимый файл XML (недействительный по специальным символам) через процесс XPL. В некоторых случаях вы можете использовать XPL-процессор вместо XML-процессора. Вы также можете использовать его для предварительной обработки недопустимых файлов без потери производительности. Искусственный интеллект, XML и Java Concurrency