Разбор XML-файла средствами встроенного языка 1С:Предприятия 8.3
Содержание
Распарсить XML в 1С можно тремя способами: потоково через объект ЧтениеXML, целиком в дерево через ПостроительDOM или в объекты через ФабрикаXDTO. Для файлов больше 50–100 МБ берите ЧтениеXML, для небольших документов со сложной вложенностью — DOM с XPath, для обмена по известной XSD-схеме — XDTO.
Все три механизма есть в платформе 8.3 и не зависят от конфигурации: код одинаково работает в Бухгалтерии, ЗУП, УТ или самописной базе. Чтобы не менять конфигурацию, загрузку обычно оформляют внешней обработкой: её пишут один раз и подключают к любой базе.
Чем разобрать XML в 1С: три инструмента и как выбрать
Во всех примерах разбираем один и тот же файл — прайс поставщика:
<?xml version="1.0" encoding="UTF-8"?>
<Catalog date="2026-10-01">
<Item id="A-001">
<Name>Бумага А4, 500 листов</Name>
<Price>450.00</Price>
<Qty>120</Qty>
</Item>
<Item id="A-002">
<Name>Папка-регистратор</Name>
<Price>189.50</Price>
<Qty>40</Qty>
</Item>
</Catalog>
Базовые объекты платформы для работы с XML:
| Объект | Как читает | Память | Когда брать |
|---|---|---|---|
ЧтениеXML | Узел за узлом, вперёд | Почти не расходует | Большие файлы, простая плоская структура |
ПостроительDOM + ДокументDOM | Весь файл в дерево | Растёт с размером файла | Небольшие файлы, нужен произвольный доступ и XPath |
ФабрикаXDTO | В объекты со свойствами | Зависит от способа | Есть XSD-схема, обмен с внешней системой |
СериализаторXDTO | В объекты самой 1С | Зависит от размера | Файл выгружен из 1С через ЗаписатьXML |
ЧтениеXML — основа всего. И DOM, и XDTO получают данные именно через него: вы открываете файл объектом ЧтениеXML и передаёте его построителю или фабрике.
💡 Комбинировать можно: идти по файлу потоково и отдельные фрагменты превращать в XDTO-объекты. Этот приём разобран в разделе про производительность.
Подготовка: где выполнять парсинг и как собрать внешнюю обработку
Разбор XML выполняйте на сервере. Там доступны транзакции, запись в базу и нет ограничений тонкого и веб-клиента на работу с файлами.
Если файл выбирает пользователь, он лежит на его компьютере, а не на сервере. Порядок такой:
- На клиенте вызовите
НачатьПомещениеФайла(илиПоместитьФайлв старых формах) — файл попадёт во временное хранилище, вы получите адрес. - Передайте адрес в серверную процедуру.
- На сервере получите двоичные данные:
ПолучитьИзВременногоХранилища(Адрес). - Запишите их во временный файл и откройте его объектом
ЧтениеXML.
&НаСервере
Процедура ЗагрузитьНаСервере(АдресФайла)
ДанныеФайла = ПолучитьИзВременногоХранилища(АдресФайла);
ИмяФайла = ПолучитьИмяВременногоФайла("xml");
ДанныеФайла.Записать(ИмяФайла);
Попытка
Товары = ПрочитатьТовары(ИмяФайла);
// ... запись в базу
Исключение
УдалитьФайлы(ИмяФайла);
ВызватьИсключение;
КонецПопытки;
УдалитьФайлы(ИмяФайла);
КонецПроцедуры
Небольшую XML-строку, полученную, например, из HTTP-ответа, писать в файл не нужно: у ЧтениеXML есть метод УстановитьСтроку(Строка).
Внешняя обработка для загрузки
Чтобы не трогать конфигурацию, код удобно держать во внешней обработке:
- В Конфигураторе:
Файл → Новый → Внешняя обработка. - Добавьте форму, на ней — поле выбора файла и кнопку «Загрузить».
- В модуле формы разместите клиентский выбор файла и серверную процедуру, как в примере выше.
- Сохраните файл с расширением
.epf.
Открыть обработку можно через Файл → Открыть в режиме 1С:Предприятие — для этого у пользователя должно быть право на интерактивное открытие внешних обработок. Платформа покажет предупреждение о защите от опасных действий, его нужно подтвердить.
В типовых конфигурациях на БСП обработку лучше зарегистрировать: Администрирование → Печатные формы, отчеты и обработки → Дополнительные отчеты и обработки. Тогда её запускают без прав на открытие произвольных файлов.
Потоковый парсинг XML через ЧтениеXML
ЧтениеXML двигается по файлу методом Прочитать(). Каждый вызов переводит курсор на следующий узел и возвращает Ложь, когда файл закончился. Тип текущего узла — в свойстве ТипУзла.
Узлы, которые встречаются чаще всего:
- 🟢
ТипУзлаXML.НачалоЭлемента— открывающий тег, тут доступны имя и атрибуты; - 📝
ТипУзлаXML.Текст— содержимое элемента, значение в свойствеЗначение; - 🔴
ТипУзлаXML.КонецЭлемента— закрывающий тег.
Функция, которая читает прайс в массив структур:
Функция ПрочитатьТовары(ИмяФайла)
Товары = Новый Массив;
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
Текущий = Неопределено;
ИмяПоля = "";
Пока Чтение.Прочитать() Цикл
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Если Чтение.ЛокальноеИмя = "Item" Тогда
Текущий = Новый Структура("Код, Наименование, Цена, Количество",
Чтение.ПолучитьАтрибут("id"), "", 0, 0);
ИначеЕсли Текущий <> Неопределено Тогда
ИмяПоля = Чтение.ЛокальноеИмя;
КонецЕсли;
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.Текст И Текущий <> Неопределено Тогда
Если ИмяПоля = "Name" Тогда
Текущий.Наименование = Чтение.Значение;
ИначеЕсли ИмяПоля = "Price" Тогда
Текущий.Цена = XMLЗначение(Тип("Число"), Чтение.Значение);
ИначеЕсли ИмяПоля = "Qty" Тогда
Текущий.Количество = XMLЗначение(Тип("Число"), Чтение.Значение);
КонецЕсли;
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Если Чтение.ЛокальноеИмя = "Item" Тогда
Товары.Добавить(Текущий);
Текущий = Неопределено;
КонецЕсли;
ИмяПоля = "";
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();
Возврат Товары;
КонецФункции
На нашем файле функция вернёт массив из двух структур. У второй: код A-002, цена 189,5, количество 40.
Что здесь важно:
ПолучитьАтрибут("id")возвращаетНеопределено, если атрибута нет. Ошибки не будет — проверяйте значение сами.Значение— всегда строка. Числа, даты и булевы приводите черезXMLЗначение(Тип(...), Строка). Функция понимает каноническую запись XML:450.00,2026-10-01T00:00:00,true.ЛокальноеИмя— имя без префикса пространства имён.Имявернётns:Item, и сравнение с"Item"не сработает.- Ненужную ветку дерева можно перескочить методом
Пропустить(), стоя на её открывающем теге.
Перебрать все атрибуты элемента, не зная их имён, можно парой ПервыйАтрибут() / СледующийАтрибут(): каждый вызов возвращает Истина, пока атрибуты есть, а имя и значение берутся из тех же Имя и Значение.
Разбор XML через DOM и поиск узлов по XPath
DOM загружает весь документ в память и даёт доступ к любому узлу в любом порядке. Код становится короче, но файл на 500 МБ так читать нельзя: дерево займёт в памяти в несколько раз больше исходного размера.
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
Построитель = Новый ПостроительDOM;
Документ = Построитель.Прочитать(Чтение);
Чтение.Закрыть();
Узлы = Документ.ПолучитьЭлементыПоИмени("Item");
Для Индекс = 0 По Узлы.Количество() - 1 Цикл
Узел = Узлы.Элемент(Индекс);
Код = Узел.ПолучитьАтрибут("id");
Имена = Узел.ПолучитьЭлементыПоИмени("Name");
Наименование = ?(Имена.Количество() > 0, Имена.Элемент(0).ТекстовоеСодержимое, "");
КонецЦикла;
ТекстовоеСодержимое возвращает текст элемента вместе с текстом всех вложенных узлов. Для листового элемента вроде <Name> это ровно его значение.
Выборка через XPath
XPath избавляет от ручного обхода. Найдём товары дороже 300 рублей:
Разыменователь = Документ.СоздатьРазыменовательПИ();
Результат = Документ.ВычислитьВыражениеXPath("//Item[Price > 300]",
Документ, Разыменователь, ТипРезультатаDOMXPath.УпорядоченныйИтераторУзлов);
Узел = Результат.ПолучитьСледующий();
Пока Узел <> Неопределено Цикл
Сообщить(Узел.ПолучитьАтрибут("id"));
Узел = Результат.ПолучитьСледующий();
КонецЦикла;
На нашем примере выведется только A-001: у второй позиции цена 189,50.
Если в корне файла объявлено пространство имён по умолчанию (xmlns="http://..."), выражение //Item ничего не найдёт. Задайте префикс через объект РазыменовательПространствИменDOM и пишите //ns:Item.
XDTO: чтение XML в типизированные объекты
XDTO превращает XML в объект, у которого элементы и атрибуты становятся свойствами. Это самый удобный путь, когда структура известна заранее.
Без схемы
Глобальная фабрика умеет читать произвольный XML:
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
Каталог = ФабрикаXDTO.ПрочитатьXML(Чтение);
Чтение.Закрыть();
ДатаПрайса = Каталог.date;
Позиции = Каталог.Item;
Главная ловушка нетипизированного XDTO — повторяющиеся элементы. Если <Item> в файле два и больше, свойство вернёт СписокXDTO. Если ровно один — сразу ОбъектXDTO, и цикл Для Каждого по нему сломается. Приводите к списку явно:
Если ТипЗнч(Позиции) = Тип("ОбъектXDTO") Тогда
Массив = Новый Массив;
Массив.Добавить(Позиции);
Позиции = Массив;
КонецЕсли;
Для Каждого Позиция Из Позиции Цикл
Цена = XMLЗначение(Тип("Число"), Позиция.Price);
КонецЦикла;
Без схемы значения листовых элементов приходят строками, поэтому XMLЗначение по-прежнему нужен.
По XSD-схеме
Если внешняя система дала XSD, постройте фабрику из неё — тогда типы приходят сразу правильные, а файл проверяется на соответствие схеме:
Фабрика = СоздатьФабрикуXDTO("C:\exchange\catalog.xsd");
ТипКаталога = Фабрика.Тип("http://example.com/catalog", "Catalog");
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
Каталог = Фабрика.ПрочитатьXML(Чтение, ТипКаталога);
Чтение.Закрыть();
Первый параметр Тип() — пространство имён схемы (targetNamespace), второй — имя типа. Для постоянного обмена схему удобнее импортировать в конфигурацию как XDTO-пакет: Общие → XDTO-пакеты, тогда фабрику создавать не нужно.
Отдельный случай — файл, выгруженный из самой 1С методом ЗаписатьXML. Его читают через СериализаторXDTO.ПрочитатьXML(Чтение): в ответ придёт готовый объект 1С (элемент справочника, документ), его останется записать.
Обработка ошибок и некорректной структуры XML-файла
Ошибки при парсинге бывают двух видов, и ловить их нужно по-разному.
Синтаксические — файл не является корректным XML: не закрыт тег, в тексте стоит голый &, кодировка в заголовке не совпадает с реальной. ЧтениеXML выбросит исключение в тот момент, когда дойдёт до сбойного места. Всё, что было прочитано до него, уже в памяти — решите, записывать ли частичный результат.
Логические — XML корректный, но не тот: нет обязательного элемента, вместо числа текст, вместо одного корня другой. Платформа их не заметит, проверки пишет разработчик.
Попытка
Товары = ПрочитатьТовары(ИмяФайла);
Исключение
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Загрузка прайса XML",
УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение "Файл не удалось разобрать: " + ТекстОшибки;
КонецПопытки;
Что проверять в логике:
- ✅ имя корневого элемента — первым же узлом после
Прочитать(); - ✅ наличие ключевых полей у каждой записи (код, цена) — пустые складывайте в отдельный список «пропущено»;
- ✅ преобразование значений —
XMLЗначениена строке450,00выбросит исключение; оберните его вПопыткадля каждого поля или нормализуйте строку заранее; - ✅ дубли кодов внутри одного файла — через
Соответствие.
💡 Пишите в журнал регистрации номер записи и код позиции, на которой случился сбой. Сообщение «ошибка разбора» без контекста в большом файле ничего не даёт.
При XDTO со схемой несоответствие структуры ловится автоматически: ПрочитатьXML выбросит исключение с указанием элемента, который не подошёл к схеме.
Как ускорить парсинг больших XML-файлов
На файлах в сотни мегабайт тормозит обычно не сам разбор, а запись в базу. Приёмы по порядку отдачи:
- Только потоковое чтение. DOM и нетипизированное XDTO для всего файла сразу на таких объёмах приводят к нехватке памяти рабочего процесса.
- Фрагменты через XDTO. Идите по файлу
ЧтениеXML, а каждую запись<Item>читайте фабрикой — код остаётся коротким, память не растёт:
Чтение.ОткрытьФайл(ИмяФайла);
Чтение.Прочитать(); // корень <Catalog>
Чтение.Прочитать(); // первый <Item>
Пока Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Цикл
Позиция = ФабрикаXDTO.ПрочитатьXML(Чтение);
// обработка Позиция.Name, Позиция.Price
КонецЦикла;
После ПрочитатьXML курсор уже стоит на следующем узле, поэтому Прочитать() в цикле не вызывается — иначе каждая вторая запись потеряется. Цикл закончится на закрывающем </Catalog>.
- Справочники — одним запросом. Не ищите номенклатуру по коду для каждой строки. Соберите все коды из файла, получите ссылки одним запросом и положите в
Соответствие. - Запись пакетами в транзакциях. Фиксируйте транзакцию каждые 500–1000 записей. Одна транзакция на весь файл держит блокировки и раздувает журнал СУБД, транзакция на каждую запись — медленная.
- Фоновое задание. Загрузку на 10+ минут запускайте в фоне, чтобы не упираться в таймаут сеанса и не блокировать пользователя.
Флаг ОбменДанными.Загрузка = Истина ускоряет запись, потому что отключает проверки и обработчики объекта. Но вместе с ними пропадают и заполнение реквизитов, и контроль. Включайте его, только если точно знаете, что делают обработчики этого объекта.
Частые проблемы при разборе XML и что с ними делать
windows-1251), а сам файл сохранён в другой (UTF-8) или наоборот. Платформа верит заголовку. Попросите поставщика исправить выгрузку или перекодируйте файл перед чтением: прочитайте его через ЧтениеТекста в правильной кодировке и передайте строку в УстановитьСтроку.& или <, либо не закрыт тег. Откройте файл в любом XML-редакторе — он покажет строку и позицию ошибки. Исправлять нужно источник выгрузки.ЧтениеXML сравнивайте ЛокальноеИмя, а не Имя. В XPath задайте префикс через разыменователь.ОбъектXDTO, а не СписокXDTO. Приводите к массиву.XMLЗначение принимает только каноническую запись: точку в дробной части и дату в формате ГГГГ-ММ-ДДTчч:мм:сс. Для 450,00 или 01.10.2026 разбирайте строку вручную.Частые вопросы
Можно ли распарсить XML в 1С без программирования?
Чем ЧтениеXML отличается от ПостроительDOM?
ЧтениеXML идёт по файлу один раз вперёд и почти не расходует память. ПостроительDOM строит дерево всего документа: удобно искать и возвращаться к узлам, но объём ограничен памятью.Как прочитать XML из строки, а не из файла?
ЧтениеXML и вызовите УстановитьСтроку(ТекстXML). Дальше всё как с файлом — можно передавать в DOM или XDTO.Как получить значение атрибута в XDTO?
Объект.id. Если имя совпадает с именем вложенного элемента, используйте схему — без неё такие случаи разбираются неоднозначно.Почему СериализаторXDTO не читает файл от внешней системы?
СериализаторXDTO понимает только формат, в котором 1С сама выгружает свои объекты. Чужой XML читайте через ФабрикаXDTO, ЧтениеXML или DOM.