XML-файл и 1С 8.3: загрузить, прочитать кодом или разобрать по схеме
Содержание
Открыть файл XML в 1С 8 можно тремя путями. Пользователь загружает его готовой командой: синхронизацией данных, загрузкой электронного документа или обработкой «Универсальный обмен данными в формате XML». Разработчик читает файл кодом: потоково через ЧтениеXML, деревом через ДокументDOM или по схеме через XDTO. А просто посмотреть содержимое удобнее всего в Конфигураторе: Файл → Открыть, тип файлов «Все файлы».
Выбор зависит от того, откуда пришёл файл. Выгрузку из другой базы 1С грузят обменом. УПД от контрагента — механизмом ЭДО. Произвольный XML от банка, маркетплейса или сайта типовая 1С «сама» не поймёт: нужна обработка, которая знает его структуру.
Конфигурация → Загрузить конфигурацию из файлов.С чего начать: что за XML и где его открывать
Сначала откройте файл любым просмотрщиком и посмотрите на первые строки. По ним видно, кто его сделал и чем его грузить.
- 🔎
<?xml version="1.0" encoding="windows-1251"?>— пролог с кодировкой. Пригодится, если при загрузке поедут буквы. - 🔎
<ФайлОбмена ВерсияФормата="2.0" ...>— файл обработки универсального обмена. Внутри есть правила или ссылка на них. - 🔎
<Message xmlns="http://www.1c.ru/SSL/Exchange/Message">и тег<Header>— сообщение синхронизации данных из типовой конфигурации. - 🔎
<Файл ИдФайл="ON_NSCHFDOPPR_...">— электронный документ по формату ФНС, например УПД. - 🔎
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses">— объект метаданных из выгрузки конфигурации в файлы.
Просто посмотреть файл в 1С можно в Конфигураторе. Меню Файл → Открыть, внизу окна выбора поставьте «Все файлы», выберите XML. Он откроется во встроенном текстовом редакторе: с поиском, но без дерева тегов.
Для больших файлов (сотни мегабайт) текстовый редактор Конфигуратора тормозит. Смотрите такой файл внешним редактором, а в 1С грузите кодом через ЧтениеXML.
Загрузка XML в 1С 8.3 без программирования
Синхронизация данных между базами
Если файл выгрузила другая типовая база (например, БП 3.0 для ЗУП 3.1 или УТ 11 для БП 3.0), он грузится через настроенную синхронизацию.
- Откройте
Администрирование → Синхронизация данных. - Включите флажок синхронизации, если он снят, и задайте префикс информационной базы.
- Откройте список настроек синхронизации и выберите ту, что соответствует второй базе.
- В настройке подключения укажите обмен через каталог на диске и путь к папке, где лежит файл.
- Запустите синхронизацию. Программа сама найдёт сообщение обмена и загрузит его.
Имя файла здесь важно. Программа ищет сообщение по имени, которое сама сформировала при выгрузке. Если файл переименовали, загрузка его не увидит.
Универсальный обмен данными в формате XML
Для разовых переносов используют обработку «Универсальный обмен данными в формате XML». В типовых конфигурациях на БСП она есть в составе, найти её проще всего через меню «Все функции».
- Включите меню «Все функции»:
Главное меню → Сервис → Параметры, флажок «Отображать команду “Все функции”». - Откройте
Все функции → Обработки → Универсальный обмен данными в формате XML. - Перейдите на закладку «Загрузка».
- Укажите путь к XML-файлу и нажмите «Загрузить данные».
Перед загрузкой чужого файла обмена сделайте резервную копию базы. Обработка создаёт и перезаписывает объекты по правилам, которые зашиты в файл. Неудачные правила могут задвоить справочники.
Электронные документы от поставщиков
УПД, накладные ТОРГ-12 и акты по формату ФНС приходят в XML. Если ЭДО не подключён, такой файл можно загрузить вручную. В БП 3.0 и УТ 11 это делается из списка документов поступления: в командной панели есть команда загрузки электронного документа из файла (обычно в подменю «ЭДО» или рядом с кнопкой «Создать»).
После выбора файла программа покажет документ, предложит сопоставить контрагента, договор и номенклатуру. Документ поступления создаётся уже по сопоставленным данным.
Внешняя обработка от разработчика
Для любого другого XML нужна обработка .epf. Откройте её через Главное меню → Файл → Открыть или подключите в справочнике дополнительных обработок: Администрирование → Печатные формы, отчёты и обработки → Дополнительные отчеты и обработки. Дальше обработка просит путь к файлу и делает своё.
Чтение XML кодом через объект ЧтениеXML
ЧтениеXML — потоковый читатель. Он идёт по файлу узел за узлом и не держит весь документ в памяти. Это лучший выбор для больших файлов и простых плоских структур.
Возьмём такой файл:
<?xml version="1.0" encoding="UTF-8"?>
<Прайс>
<Товар Код="001">
<Наименование>Бумага А4</Наименование>
<Цена>420.50</Цена>
</Товар>
<Товар Код="002">
<Наименование>Скрепки 28 мм</Наименование>
<Цена>85</Цена>
</Товар>
</Прайс>
Код, который читает его в таблицу значений целиком:
&НаСервереБезКонтекста
Функция ПрочитатьПрайс(ПутьКФайлу)
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Код");
Таблица.Колонки.Добавить("Наименование");
Таблица.Колонки.Добавить("Цена");
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлу);
Строка = Неопределено;
ТекущееПоле = "";
Пока Чтение.Прочитать() Цикл
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Если Чтение.Имя = "Товар" Тогда
Строка = Таблица.Добавить();
Строка.Код = Чтение.ПолучитьАтрибут("Код");
Иначе
ТекущееПоле = Чтение.Имя;
КонецЕсли;
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.Текст И Строка <> Неопределено Тогда
Если ТекущееПоле = "Наименование" Тогда
Строка.Наименование = Чтение.Значение;
ИначеЕсли ТекущееПоле = "Цена" Тогда
Строка.Цена = Число(Чтение.Значение);
КонецЕсли;
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
ТекущееПоле = "";
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();
Возврат Таблица;
КонецФункции
Что здесь важно:
- 📌
Прочитать()возвращаетЛожьв конце файла, поэтому цикл завершается сам. - 📌 Атрибуты (
Код="001") берут черезПолучитьАтрибутв момент, когда читатель стоит на начале элемента. - 📌 Текст элемента — отдельный узел типа
Текст. Его значение вЧтение.Значение. - 📌
Число("420.50")понимает точку как разделитель. Запятую в цене придётся заменить черезСтрЗаменить.
Если XML пришёл строкой (из HTTP-запроса или реквизита), вместо ОткрытьФайл вызовите Чтение.УстановитьСтроку(ТекстXML). Остальной код тот же.
Файл на компьютере пользователя
Код на сервере не видит диск пользователя. Файл сначала передают на сервер. На клиенте пользователь выбирает файл и помещает его во временное хранилище (метод НачатьПомещениеФайлаНаСервер или более старые варианты помещения файла). На сервере данные достают и пишут во временный файл:
&НаСервере
Процедура ЗагрузитьИзХранилища(АдресВХранилище)
Данные = ПолучитьИзВременногоХранилища(АдресВХранилище);
ИмяВременного = ПолучитьИмяВременногоФайла("xml");
Данные.Записать(ИмяВременного);
Результат = ПрочитатьПрайс(ИмяВременного);
УдалитьФайлы(ИмяВременного);
// ТаблицаТоваров — реквизит формы типа ТаблицаЗначений
ЗначениеВРеквизитФормы(Результат, "ТаблицаТоваров");
КонецПроцедуры
Таблицу значений с сервера на клиент напрямую не вернуть, поэтому результат кладём в реквизит формы. Другой вариант — сразу создавать документы на сервере.
Работа со структурой через DOM-модель
DOM загружает весь документ в память и строит дерево. Зато по дереву можно ходить в любом порядке, искать узлы по имени и по XPath. Это удобно для файлов со сложной вложенностью, где потоковое чтение превращается в кашу из флагов.
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлу);
Построитель = Новый ПостроительDOM;
Документ = Построитель.Прочитать(Чтение);
Чтение.Закрыть();
Товары = Документ.ПолучитьЭлементыПоИмени("Товар");
Для Индекс = 0 По Товары.Количество() - 1 Цикл
Узел = Товары.Элемент(Индекс);
Код = Узел.ПолучитьАтрибут("Код");
Наименование = Узел.ПолучитьЭлементыПоИмени("Наименование").Элемент(0).ТекстовоеСодержимое;
Сообщить(Код + " — " + Наименование);
КонецЦикла;
Для точечного поиска пригодится XPath. Например, найти товар с кодом 002:
Разыменователь = Новый РазыменовательПространствИменDOM(Документ);
Результат = Документ.ВычислитьВыражениеXPath("//Товар[@Код='002']", Документ, Разыменователь);
Узел = Результат.ПолучитьСледующий();
Если Узел <> Неопределено Тогда
Сообщить(Узел.ТекстовоеСодержимое);
КонецЕсли;
Если в корне файла объявлено пространство имён по умолчанию (xmlns="..."), XPath без префикса ничего не найдёт. Создайте разыменователь с явным префиксом и пишите в выражении //p:Товар.
Когда что выбирать:
| Способ | Когда подходит | Ограничения |
|---|---|---|
ЧтениеXML | Большие файлы, плоские списки, разовая загрузка | Только вперёд, логику вложенности пишете сами |
ДокументDOM | Сложная вложенность, поиск по XPath, правка файла | Весь файл в памяти; файл в сотни мегабайт может упереться в память |
| XDTO | Есть XSD-схема, формат стабилен, нужна проверка | Нужна схема и пакет; ошибки проверки бывают многословными |
Разбор XML по схеме через XDTO-пакеты
XDTO превращает XML в объекты с полями. Читать становится просто: Объект.Товар[0].Цена вместо цикла по узлам. Платформа ещё и проверяет файл на соответствие схеме.
Порядок работы такой:
- Получите XSD-схему формата. Её обычно публикует автор формата: ФНС, банк, маркетплейс.
- В Конфигураторе (или в расширении) откройте ветку
Общие → XDTO-пакетыи импортируйте схему через контекстное меню. - Запомните пространство имён пакета (свойство «URI пространства имён») и имя корневого типа.
- Читайте файл через фабрику:
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлу);
ТипКорня = ФабрикаXDTO.Тип("http://example.com/price", "Прайс");
Прайс = ФабрикаXDTO.ПрочитатьXML(Чтение, ТипКорня);
Чтение.Закрыть();
Для Каждого Товар Из Прайс.Товар Цикл
Сообщить(Товар.Наименование);
КонецЦикла;
Если элемент в схеме может встречаться несколько раз, в объекте XDTO он придёт списком. Если один раз — одиночным значением. Отсюда частая ошибка: код написан под список, а в файле одна позиция.
Файлы, записанные самой 1С
Отдельный случай — XML, который 1С записала глобальной функцией ЗаписатьXML или через СериализаторXDTO. Внутри него элементы вида <CatalogObject.Номенклатура>. Такой файл читают обратно функцией ПрочитатьXML(Чтение): она вернёт объект 1С, который останется записать. Схему подключать не нужно, платформа знает свои типы.
Типовую выгрузку конфигурации в XML-файлы так не читают. Это исходники, а не данные, и место им в Конфигураторе.
Ошибки кодировки, пути к файлу и прав доступа
<?xml ...?> обязан быть первым символом файла.Ещё несколько деталей, которые всплывают на практике:
- 🗂 Сервер 1С на Linux различает регистр в путях.
/mnt/obmen/Price.xmlи/mnt/obmen/price.xml— разные файлы. - 🗂 В веб-клиенте прямого доступа к диску нет вообще. Только выбор файла пользователем и передача через хранилище.
- 🗂 Длинные пути с кириллицей и пробелами работают, но в командных файлах и планировщике их надо брать в кавычки.
Как посмотреть структуру XML и отладить разбор
Прежде чем писать код, разберитесь со структурой файла. Иначе цикл будет искать элемент, которого нет.
Чем посмотреть дерево:
- Браузер. Перетащите XML в окно Chrome или Firefox — он покажет дерево со сворачиванием узлов. Если файл битый, браузер укажет строку ошибки.
- Notepad++ с плагином XML Tools: форматирование отступами, проверка корректности, проверка по XSD.
- VS Code: подсветка, сворачивание, форматирование документа.
Как отлаживать в 1С:
- 🐞 Поставьте точку останова внутри цикла
Пока Чтение.Прочитать()и смотрите в таблоЧтение.ТипУзла,Чтение.Имя,Чтение.Значение. Сразу видно, на каком узле логика разошлась с файлом. - 🐞 Для DOM смотрите в отладчике
Документ.ЭлементДокументаи раскрывайте дочерние узлы. - 🐞 Пустые узлы
Текстиз переводов строк и отступов — норма. Отсекайте их проверкойПустаяСтрока(Чтение.Значение).
Если файл пришёл одной строкой без переносов, его удобно переформатировать прямо в 1С. Прочитайте его в DOM и запишите обратно с отступами:
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл(ПутьКНовомуФайлу, Новый ПараметрыЗаписиXML("UTF-8", "1.0", Истина));
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(Документ, Запись);
Запись.Закрыть();
Третий параметр ПараметрыЗаписиXML включает отступы. Полученный файл читается глазами без внешних программ.
Частые вопросы
Можно ли открыть XML в 1С двойным щелчком, как Excel?
Почему одна и та же обработка в файловой базе работает, а в серверной нет?
Какой способ быстрее на файле в 500 МБ?
ЧтениеXML. Он не строит дерево в памяти. DOM и XDTO на таком объёме могут исчерпать память рабочего процесса.Как загрузить XML из Excel-подобной таблицы в 1С?
Нужна ли XSD-схема, чтобы прочитать файл?
ЧтениеXML и DOM — нет. Для XDTO с типизированным разбором и проверкой — да, её импортируют в XDTO-пакет.