XML: как проверить на ошибки и превратить в JSON

8 ноября 2026 г.
XML: как проверить на ошибки и превратить в JSON

К XML приходят по разным причинам. Выгрузка из учётной системы, sitemap для поисковика, RSS-лента, конфигурация сборки, ответ веб-сервиса: всё это приходит в XML, хотя половина приложений ждёт JSON. Дальше начинается неприятная часть: файл не открывается, потому что в нём один незакрытый тег, а в логе об этом нет ни слова. Разберёмся, как устроены оба формата, как найти ошибку в XML за десять секунд и как перевести одно в другое, не потеряв данные по дороге.

Чем XML отличается от JSON

XML это язык разметки: текст, в котором смысл несут не сами слова, а названия тегов. JSON это формат данных: структура из ключей и значений, где тип каждого значения известен заранее. Сравните два описания одной и той же записи.

Одна и та же запись в двух форматах
XML:
<person><name>Иван</name><age>34</age></person>

JSON:
{"name":"Иван","age":34}

Разница видна сразу. В XML возраст это текст «34», и пока не сказано, что это число, оно текстом и останется. В JSON 34 это число, и его можно складывать. В XML есть атрибуты, которые не содержат значения, а только свойства, в JSON для свойств используются отдельные ключи. В XML нет встроенных типов true, false и null: логическое значение или пустоту приходится описывать самому или задавать в схеме, тогда как в JSON эти типы есть по определению.

  • XML строгий: имя тега, регистр символов, кавычки вокруг значений атрибутов проверяются.
  • JSON строг к записи, но снисходителен к смыслу: только двойные кавычки, никаких комментариев и никакой запятой в конце.
  • В XML есть комментарии, XML-декларация, инструкции обработки и секции CDATA. В JSON ничего из этого нет.
  • В XML повторяющийся элемент просто повторяется, а в JSON одинаковые элементы собираются в массив.
  • В XML есть пространства имён, и одно и то же имя может принадлежать разным словарям. В JSON такой проблемы нет.

Когда применять XML, а когда JSON

Выбор на практике сводится к тому, кто первый задал формат. Если формат выбираете вы, берите JSON: он компактнее, разбирается без предварительной настройки и одинаково понимается в браузере, в мобильном приложении и в серверном коде.

  • JSON, когда данные идут между вашим кодом и браузером или мобильным приложением.
  • JSON, когда ответ отдаётся как API и важна скорость разбора.
  • XML, когда формат задан извне: sitemap, RSS, выгрузка, отчёт, документ, который подписывается электронной подписью.
  • XML, когда нужны комментарии, порядок элементов или привязка к схеме XSD.
  • Если данные приходят таблицей, а не деревом, сначала доведите их до JSON по инструкции как перевести CSV в JSON, а дальше работайте уже с объектом.

Проверка XML на ошибки: что ищет валидатор

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

  • Незакрытый тег: <a><b>текст</a>. Закрывающий тег обязан совпадать с последним открытым.
  • Лишний закрывающий тег: </div> без парного <div>.
  • Кавычки в атрибутах: <a href=page.html>. В XML кавычки обязательны, а внутри значения не может стоять символ <.
  • Неэкранированный амперсанд: <p>Цена & доставка</p>. Символ & в XML всегда начинает сущность, поэтому его пишут как &amp;.
  • Отсутствующий слеш у одиночного элемента: <br> вместо <br/>.
  • Пустой документ или текст вне корневого элемента.
Битый XML
<catalog>
  <book id="1">
    <title>Дроны</title>
    <price currency="RUB">1990</price>
  </book>
  <book id="2">
    <title>Верёвки</title>
  </catalog>

Что здесь не так: тег <book id="2"> открыт, но закрыт не был, а </catalog> закрыл его вместо этого. Правильный вариант ставит </book> перед </catalog>. Форматтер ловит это и указывает на неожиданный закрывающий тег. Делается проверка так: файл вставляется в форматтер XML и нажимается Format. Разбор парности тегов занимает секунды, и ошибиться в нём трудно.

Что такая проверка ловит, а что нет

Здесь важно не переоценить возможности. Проверка парности тегов находит незакрытый и лишний закрывающий тег, но вот кавычки в атрибутах, неэкранированный амперсанд и опечатку в имени атрибута она пропустит: структура от этого не рассыпается. Для настоящей проверки существуют схемы XSD и DTD, и это уже работа настоящего валидатора, а не простого форматтера.

Второе ограничение связано с тем, что проверка идёт по тегам, а не по содержимому. Опечатку в тексте форматтер не заметит, потому что текст для него просто символы. Зато вложенность вроде <b><i></b></i> он посчитает ошибочной, и это правильно: элементы должны закрываться в обратном порядке, как стек.

Namespace и префиксы

Пространства имён нужны, чтобы два разных словаря в одном документе не сливались. Типичный пример: RSS-лента использует пространство имён для стандартных элементов, а внутри лежит Atom-вставка или медиа-расширение, и элементы с одинаковым именем из разных словарей должны оставаться разными.

Два словаря в одном документе
<feed xmlns="http://www.w3.org/2005/Atom"
      xmlns:media="http://search.yahoo.com/mrss/">
  <title>Новости</title>
  <media:thumbnail url="pic.jpg"/>
</feed>

Атрибут xmlns задаёт пространство имён по умолчанию: все элементы без префикса принадлежат этому словарю. Атрибут xmlns:media объявляет префикс media и привязывает его к другому адресу. Сам адрес в данных не появляется, он работает как метка: важно только, чтобы он совпадал в объявлении и в использовании. Правило простое, если префикс встречается в документе, он обязан быть объявлен, иначе документ невалиден.

Разница с JSON заметна. В JSON нет ни префиксов, ни пространств имён, и ключ title всегда значит ровно одно и то же. В XML имя элемента это комбинация локального имени и пространства имён, и именно поэтому при конвертации в JSON префиксы приходится обрабатывать отдельно.

Документ или фрагмент

Полноценный XML-документ начинается с необязательной, но очень желательной XML-декларации, в которой указывается версия и кодировка.

Декларация и корневой элемент
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <item id="7">Верёвки</item>
</catalog>

Правила такие: у документа ровно один корневой элемент, все остальные находятся внутри него, а декларация стоит первой, без пробелов и без невидимого символа перед ней. Фрагмент, вырезанный из документа, декларации не содержит и корневого элемента может не иметь. Многие парсеры принимают фрагмент, но не примут документ без единственного корня.

Кодировку лучше указывать явно. Файл может выглядеть нормально в редакторе и посыпаться при разборе, если декларация говорит про UTF-8, а байты лежат в windows-1251. Формат XML 1.0 был опубликован как рекомендация W3C в 1998 году, и требование объявлять кодировку в декларации с тех пор не менялось.

Как превратить XML в JSON: правила и что теряется

Готового преобразования одно в другое не существует, поэтому приходится договариваться о правилах. Рабочая схема выглядит так: имя элемента становится ключом, текст внутри становится значением, повторяющиеся элементы собираются в массив, а атрибуты уезжают в отдельный объект с ключом @attributes.

XML и результат конвертации
<item id="7" stock="3">
  <name>Верёвки</name>
  <price currency="RUB">1990</price>
  <tag>туризм</tag>
  <tag>вязка</tag>
</item>

JSON:
{
  "@attributes": { "id": "7", "stock": "3" },
  "name": "Верёвки",
  "price": { "@attributes": { "currency": "RUB" }, "#text": "1990" },
  "tag": ["туризм", "вязка"]
}

Заметьте две особенности. Первая: числа остаются строками, потому что в XML «1990» это текст, и объявить его числом можно только по внешнему правилу, например по схеме. Вторая: одиночный тег tag превратился в строку, а два одинаковых тега собрались в массив. Из-за этого структура зависит от данных, и потребителю JSON приходится обрабатывать оба варианта.

Что теряется при конвертации

  • Порядок элементов, если он не отражался в именах ключей. В JSON объект не упорядочен, и последовательность «сначала цена, потом название» нигде не сохранится.
  • Смешанное содержимое: <p>Текст <b>жирный</b> продолжение</p> превращается в нечто невнятное, потому что у элемента появляется смесь текста и вложенного узла.
  • Префиксы пространств имён, если их не разобрать заранее. Ключ media:thumbnail в JSON выглядит странно, и разумнее заменить его на thumbnail с отдельной пометкой об источнике.
  • Различие между элементом без атрибутов и элементом с пустым значением: <a/> и <a></a> в JSON превращаются в null и в пустую строку, а это разные вещи.
  • Комментарии и XML-декларация, если не вынести их отдельно.

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

Обратно: JSON в XML

Обратное преобразование проще, потому что JSON устроены как дерево ключей, а ключи прекрасно превращаются в имена тегов. Правила зеркальные.

JSON → XML
{ "name": "Верёвки", "tags": ["туризм", "вязка"] }

<root>
  <name>Верёвки</name>
  <tags>туризм</tags>
  <tags>вязка</tags>
</root>

Тонкость в том, что массив в JSON не имеет имени. Пока ключ tags становится корневым тегом, всё выглядит естественно, но если на верхнем уровне окажется массив без объекта-обёртки, разбирать его будет нечем. Поэтому JSON для XML обычно заворачивают в объект с именем корня. И ещё: имя ключа должно быть корректным XML-именем, без пробелов и обязательно с буквы или подчёркивания на первом месте.

Проверить результат можно в форматтере JSON: он показывает ошибку с указанием строки и столбца, если структура нарушена, и строит дерево по данным. Подробнее о том, как проверять JSON и не сломать его при правке, написано в статье JSON: как проверить и отформатировать.

Типичные ошибки

  • Закрыли тег не в том порядке, в каком открыли: <a><b></a></b>. Закрывать нужно в обратном порядке, как стек.
  • Забыли экранировать амперсанд в ссылке: параметр a=1&b=2 внутри атрибута приведёт к ошибке, нужно &amp;.
  • Скопировали XML из выгрузки, где разделителем служит & вместо &amp;.
  • Поверили, что JSON разрешает комментарии. Не разрешает, не пропускает одинарные кавычки и не терпит висячую запятую.
  • Считают, что при конвертации в JSON числа останутся числами. Без схемы они станут строками.
  • Объявили префикс в одном файле и забыли про него в другом. Каждый XML-документ самодостаточен: объявление пространства имён из соседнего файла не переносится.

Частые вопросы

Чем XML лучше JSON?

Возможностей у XML больше: комментарии, инструкции обработки, секции CDATA, пространства имён, привязка к схеме XSD, электронная подпись. Поэтому там, где формат задан извне или требуется юридическая значимость документа, XML остаётся стандартом. Но разбирать его дороже, а объём больше, поэтому внутри приложений обычно побеждает JSON.

Валидатор пишет, что XML валиден, а программа его не читает. Что делать?

Проверьте три вещи, которые настоящие парсеры ловят строже, чем простой счётчик тегов. Первое: кодировка. Объявление UTF-8 при фактических байтах в windows-1251 даёт битые символы, а иногда и ошибку разбора. Второе: XML-декларация не должна быть ничем предшествована, никакого пробела и никакого невидимого символа в начале файла. Третье: в значениях атрибутов не должно быть символа <, а амперсанд должен быть экранирован.

Что такое CDATA и когда это нужно?

Это секция, внутри которой содержимое не разбирается как разметка: <![CDATA[ любой текст, даже с тегами <b> ]]>. Ею пользуются, когда в данные попадает чужой HTML или кусок кода. Ограничений два: последовательность ]]> внутри секции недопустима, и вложенная секция внутри CDATA тоже не работает, потому что закрывающая пара уже использована.

Можно ли сжать XML?

Да, и это отдельный режим работы. Убираются пробелы между тегами и переносы строк, а содержательный текст сохраняется. Сжатый XML плохо читается, поэтому его используют для передачи по сети, а для чтения оставляют обычный отформатированный вид. В минификаторе сжатие доступно для JavaScript, CSS и HTML, а для XML отдельная кнопка есть в форматтере.

Что такое XSD и зачем он, если есть JSON Schema?

XSD это схема, описывающая структуру XML-документа: какие элементы допустимы, в каком порядке, какие у них типы. Проверка по XSD даёт строгий ответ, что документ соответствует ожиданиям, вплоть до значений и ограничений. JSON Schema делает то же самое для JSON, и в валидаторе JSON Schema можно проверить данные по готовой схеме. Схемы нужны тогда, когда с документом работает не только ваш код.

Проверяйте XML в два прохода: сначала парность тегов в форматтере, потом кодировку и экранирование глазами. Большинство невалидных файлов ломается ровно на этих двух шагах, а не на чём-то экзотическом.

Читайте также