XML в 2026 году — как читать, сравнивать и не ненавидеть его

Обновлено

XML не умер. Оно присутствует в ваших ответах SOAP, SVG-файлах, Maven-постройках и sitemaps. Вот как читать пространства имен, писать полезные XPath и сравнивать структуру XML — а не только текстовую часть.

XML не умер. Он есть в ваших SOAP-ответах, SVG-файлах, сборках Maven и sitemaps. Вот как читать «супу» пространств имен, писать полезные XPath и сравнивать XML структурно, а не текстово.
Реклама · УДАЛИТЬ?

Вы в 2026 году и получили XML. Возможно, это SOAP-интерфейс от банка, сборка Maven, которая отказывается собираться, RSS-канал, который нужно разобрать, или SVG, в котором 40 строк объявления пространств имен перед первой фигурой. В любом случае, вам нужно пройти через это без потери дня.

Почему XML всё ещё повсюду

XML прошёл свой десятилетний период доминирования, затем JSON съел его обед для REST-интерфейсов — и тем не менее он не исчез. В 2026 году вы столкнётесь с XML в этих местах:

  • SOAP/WSDL API — банки, страховые платформы, системы здравоохранения и государственные услуги. Объём установленной базы огромен и почти ничего из этого не переписывается. Проект «мы перейдём на REST» был сокращён с 2019 года.
  • SVG — любое сложное иконку, иллюстрацию или диаграмму, экспортированное из Figma, Illustrator или любого другого инструмента дизайна, — это документ XML. Таковы также все узлы, которые добавляет D3 в DOM.
  • Maven pom.xml — вся экосистема Java, а также любой проект на JVM, использующий вариант XML в Gradle. Если вы работаете с устаревшим сервисом на Java, вы редактируете XML.
  • sitemap.xml — каждый сайт, серьёзно работающий с SEO, генерирует такой файл. WordPress, Hugo, Next.js — все производят его. Когда ваш валидатор сitemap выявляет ошибку, вы отлаживаете XML.
  • RSS и Atom-фиды — подкасты, агрегаторы новостей, уведомления о мониторинге. Atom — это XML. RSS 2.0 — это XML. Половина поставщиков данных, с которыми вы интегрируетесь, по-прежнему предлагают RSS как свой «интерфейс».
  • Office Open XML — .docx и .xlsx — это архивы ZIP. Распакуйте один и вы найдёте сотни XML-файлов. Когда вы парсите документы Word или таблицы Excel программно, вы парсите XML, даже если не знаете об этом.

Чтение документа с множеством пространств имен

То, что делает XML трудным для чтения, — это не угловые скобки, а пространства имен. Вот типичный ответ SOAP:

<soap:Envelope
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:ns0="http://example.com/orders/v2"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soap:Header>
    <ns0:AuthHeader>
      <ns0:token>abc123</ns0:token>
    </ns0:AuthHeader>
  </soap:Header>
  <soap:Body>
    <ns0:GetOrderResponse>
      <ns0:order xsi:type="ns0:OrderV2">
        <ns0:id>ORD-8842</ns0:id>
        <ns0:status>shipped</ns0:status>
        <ns0:items>
          <ns0:item>
            <ns0:sku>WIDGET-A</ns0:sku>
            <ns0:qty>3</ns0:qty>
          </ns0:item>
        </ns0:items>
      </ns0:order>
    </ns0:GetOrderResponse>
  </soap:Body>
</soap:Envelope>

Три вещи, на которые стоит обратить внимание:

  • URI — это идентификатор, а не префикс. xmlns:soap="http://..." и xmlns:env="http://..." Те, что указывают на один и тот же URL, относятся к одному и тому же пространству имен. Разные документы могут использовать разные префиксы для одного и того же пространства имен — ваш парсер должен это учитывать. Префикс — это просто локальный сокращённый вариант.
  • xsi:type это подсказка схемы, а не волшебство. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" это шаблон. xsi:type Атрибут указывает валидатору, какая схема применима к этому элементу. Вы можете проигнорировать его в большинстве случаев парсинга, если вы не выполняете формальную валидацию схемы.
  • Форматируйте перед тем, как читать. Если XML пришёл в сжатом виде, сначала его нужно форматировать. На любой системе Unix: xmllint --format file.xmlИли быстро: python3 -c "import sys; from xml.dom.minidom import parseString; print(parseString(sys.stdin.read()).toprettyxml())".

Основы XPath, которые действительно важны

XPath — это язык запросов для навигации по деревьям XML. Изучение 10%, охватывающего 90% реальных случаев использования, занимает около 20 минут:

# Absolute path from root
/soap:Envelope/soap:Body/ns0:GetOrderResponse

# Anywhere in the tree
//ns0:order

# Attribute access
//ns0:order/@xsi:type

# Predicate: filter by child element value
//ns0:item[ns0:sku='WIDGET-A']

# Text content
//ns0:status/text()

# Namespace-agnostic — works even if you don't know the prefixes
//*[local-name()='order']
//*[local-name()='item'][*[local-name()='sku']='WIDGET-A']

# Count
count(//ns0:item)

The local-name() функция — это выходной механизм для ситуаций, когда префиксы неопределены или несогласованы. Она ищет по имени элемента, игнорируя URI пространства имен. Хорошо подходит для экспериментальной работы; используйте с осторожностью в производственной среде, потому что два элемента из разных пространств имен могут иметь одинаковое локальное имя, и вы будете автоматически совпадать с обоими.

Чтобы протестировать XPath без написания скрипта, xmllint --shell предоставляет вам интерактивную сессию:

xmllint --shell order.xml
# Type XPath expressions at the > prompt
# > xpath //ns0:status/text()

В Python, lxml обрабатывает XPath с учётом пространства имен чисто:

from lxml import etree

tree = etree.parse("order.xml")
ns = {
    "soap": "http://schemas.xmlsoap.org/soap/envelope/",
    "ns0":  "http://example.com/orders/v2",
}
status = tree.xpath("//ns0:status/text()", namespaces=ns)
print(status[0])  # "shipped"

Сравнение XML: структурное и текстовое

Здесь большинство разработчиков тратят время: diff old.xml new.xml не сообщает, что изменилось в документе. Оно сообщает, что изменилось в тексте. Эти вещи не совпадают.

Три случая, когда текстовое сравнение даёт шум при идентичных XML-документах:

  • Порядок атрибутов. <item id="1" type="widget"> и <item type="widget" id="1"> это один и тот же элемент. Порядок атрибутов в XML не имеет значения. Текстовое сравнение фиксирует это как изменение.
  • Переименование префикса пространства имен. Разный префикс, одинаковый URI, семантически идентичный документ. Текстовое сравнение видит изменение. Структурное сравнение не видит этого.
  • Незначимый пробел. Выполните любое форматирование архива над сжатым документом и текстовое сравнение превратится в стену шума. Структурное сравнение полностью игнорирует это.

Для быстрого структурного сравнения без написания кода, IO Tools XML Diff Comparator обрабатывает это в браузере — вставьте два документа, получите различия на уровне элементов, а не на уровне строк. Полезно, когда вы отлаживаете, почему ответ изменился между версиями API, и не хотите писать скрипт для одноразового проверки.

Если вам нужно структурное сравнение в коде, Python-библиотека xmldiff — это самый чистый открытый источник:

pip install xmldiff

from xmldiff import main

result = main.diff_files("old.xml", "new.xml")
# Returns typed edit operations:
# [UpdateTextIn(node='/order[1]/status[1]', text='delivered'),
#  InsertNode(target='/order[1]', tag='tracking', position=3)]

Результат — это список типизированных операций редактирования — InsertNode, DeleteNode, UpdateTextIn, MoveNode — то, что вы действительно хотите при аудите изменений схемы между версиями API или при написании скрипта для создания патча. Алгоритм работает за O(n²) от количества узлов, поэтому он замедляется при больших документах, но для конфигурационных файлов и ответов API это нормально.

Когда стоит конвертировать в JSON и двигаться дальше

Иногда правильным решением является отказ от XML на границе вашего сервиса и работа с JSON для всей логики приложения. Если вы используете SOAP-интерфейс в Node.js-сервисе, поддержка XML-парсинга на всей системе хуже, чем конвертация на входе.

  • Node.js: xml2js — стандартный выбор. Делает то, что говорит. По умолчанию вывод обёртывает всё в массивы, даже для одиночных элементов; установите explicitArray: false для ответов с фиксированной структурой.
  • Python: xmltodict — конвертация за один шаг. Та же проблема с массивами при повторяющихся элементах, но подходит для ответов с известной структурой, где вы контролируете схему.
  • Java: Jackson XML module — если вы уже используете Jackson для JSON, то jackson-dataformat-xml расширяет XML напрямую в POJO без отдельной стека парсера.

Для экспериментов — определения имен полей и структуры вложенности до написания кода парсинга — IO Tools XML-to-JSON converter быстрее, чем написание временного скрипта.

Краткий справочник

Когда вы смотрите на незнакомый XML:

  • Сначала форматируйте его: xmllint --format file.xml
  • Проверьте, что он хорошо сформирован: xmllint --noout file.xml (выход 0, если валидный)
  • Читайте локальные имена элементов, игнорируйте префиксы пространства имен, пока не понадобятся
  • Навигируйте с помощью XPath, когда префиксы неясны //*[local-name()='element'] Сравнивайте структурно, а не текстово — сравнение по строкам в XML обычно даёт шум
  • Конвертируйте в JSON на границе сервиса, если вы выполняете реальную обработку в дальнейшем
  • XMLVerbose, объявления пространств имен — это тяжёлый труд, и инструменты отражают три десятилетия эволюции стандартов. Ни одно из этого не меняется. Но как только вы понимаете, где возникает сопротивление, оно перестаёт удивлять — и вы перестаёте тратить время на текстовые сравнения переформатированных документов.

XML в 2026 году — как читать, сравнивать и не ненавидеть его 2

Хотите убрать рекламу? Откажитесь от рекламы сегодня

Установите наши расширения

Добавьте инструменты ввода-вывода в свой любимый браузер для мгновенного доступа и более быстрого поиска

в Расширение Chrome в Расширение края в Расширение Firefox в Расширение Opera

Табло результатов прибыло!

Табло результатов — это интересный способ следить за вашими играми, все данные хранятся в вашем браузере. Скоро появятся новые функции!

Реклама · УДАЛИТЬ?
Реклама · УДАЛИТЬ?
Реклама · УДАЛИТЬ?

новости с техническими моментами

Примите участие

Помогите нам продолжать предоставлять ценные бесплатные инструменты

Купи мне кофе
Реклама · УДАЛИТЬ?