XML в 2026 году — как читать, сравнивать и не ненавидеть его
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
Установите наши расширения
Добавьте инструменты ввода-вывода в свой любимый браузер для мгновенного доступа и более быстрого поиска
恵 Табло результатов прибыло!
Табло результатов — это интересный способ следить за вашими играми, все данные хранятся в вашем браузере. Скоро появятся новые функции!
Подписаться на новости
все Новые поступления
всеОбновлять: Наш последний инструмент был добавлен 8 июня 2026 года
