XML-файл и 1С 8.3: загрузить, прочитать кодом или разобрать по схеме

· 10 мин

Содержание

Открыть файл XML в 1С 8 можно тремя путями. Пользователь загружает его готовой командой: синхронизацией данных, загрузкой электронного документа или обработкой «Универсальный обмен данными в формате XML». Разработчик читает файл кодом: потоково через ЧтениеXML, деревом через ДокументDOM или по схеме через XDTO. А просто посмотреть содержимое удобнее всего в Конфигураторе: Файл → Открыть, тип файлов «Все файлы».

Выбор зависит от того, откуда пришёл файл. Выгрузку из другой базы 1С грузят обменом. УПД от контрагента — механизмом ЭДО. Произвольный XML от банка, маркетплейса или сайта типовая 1С «сама» не поймёт: нужна обработка, которая знает его структуру.

Какой XML у вас на руках?

С чего начать: что за 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), он грузится через настроенную синхронизацию.

  1. Откройте Администрирование → Синхронизация данных.
  2. Включите флажок синхронизации, если он снят, и задайте префикс информационной базы.
  3. Откройте список настроек синхронизации и выберите ту, что соответствует второй базе.
  4. В настройке подключения укажите обмен через каталог на диске и путь к папке, где лежит файл.
  5. Запустите синхронизацию. Программа сама найдёт сообщение обмена и загрузит его.

Имя файла здесь важно. Программа ищет сообщение по имени, которое сама сформировала при выгрузке. Если файл переименовали, загрузка его не увидит.

Универсальный обмен данными в формате XML

Для разовых переносов используют обработку «Универсальный обмен данными в формате XML». В типовых конфигурациях на БСП она есть в составе, найти её проще всего через меню «Все функции».

  1. Включите меню «Все функции»: Главное меню → Сервис → Параметры, флажок «Отображать команду “Все функции”».
  2. Откройте Все функции → Обработки → Универсальный обмен данными в формате XML.
  3. Перейдите на закладку «Загрузка».
  4. Укажите путь к 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].Цена вместо цикла по узлам. Платформа ещё и проверяет файл на соответствие схеме.

Порядок работы такой:

  1. Получите XSD-схему формата. Её обычно публикует автор формата: ФНС, банк, маркетплейс.
  2. В Конфигураторе (или в расширении) откройте ветку Общие → XDTO-пакеты и импортируйте схему через контекстное меню.
  3. Запомните пространство имён пакета (свойство «URI пространства имён») и имя корневого типа.
  4. Читайте файл через фабрику:
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлу);
ТипКорня = ФабрикаXDTO.Тип("http://example.com/price", "Прайс");
Прайс = ФабрикаXDTO.ПрочитатьXML(Чтение, ТипКорня);
Чтение.Закрыть();

Для Каждого Товар Из Прайс.Товар Цикл
    Сообщить(Товар.Наименование);
КонецЦикла;

Если элемент в схеме может встречаться несколько раз, в объекте XDTO он придёт списком. Если один раз — одиночным значением. Отсюда частая ошибка: код написан под список, а в файле одна позиция.

Файлы, записанные самой 1С

Отдельный случай — XML, который 1С записала глобальной функцией ЗаписатьXML или через СериализаторXDTO. Внутри него элементы вида <CatalogObject.Номенклатура>. Такой файл читают обратно функцией ПрочитатьXML(Чтение): она вернёт объект 1С, который останется записать. Схему подключать не нужно, платформа знает свои типы.

Типовую выгрузку конфигурации в XML-файлы так не читают. Это исходники, а не данные, и место им в Конфигураторе.

Ошибки кодировки, пути к файлу и прав доступа

Диагностика: выберите симптом

Ещё несколько деталей, которые всплывают на практике:

  • 🗂 Сервер 1С на Linux различает регистр в путях. /mnt/obmen/Price.xml и /mnt/obmen/price.xml — разные файлы.
  • 🗂 В веб-клиенте прямого доступа к диску нет вообще. Только выбор файла пользователем и передача через хранилище.
  • 🗂 Длинные пути с кириллицей и пробелами работают, но в командных файлах и планировщике их надо брать в кавычки.

Как посмотреть структуру XML и отладить разбор

Прежде чем писать код, разберитесь со структурой файла. Иначе цикл будет искать элемент, которого нет.

Чем посмотреть дерево:

  1. Браузер. Перетащите XML в окно Chrome или Firefox — он покажет дерево со сворачиванием узлов. Если файл битый, браузер укажет строку ошибки.
  2. Notepad++ с плагином XML Tools: форматирование отступами, проверка корректности, проверка по XSD.
  3. VS Code: подсветка, сворачивание, форматирование документа.

Как отлаживать в 1С:

  • 🐞 Поставьте точку останова внутри цикла Пока Чтение.Прочитать() и смотрите в табло Чтение.ТипУзла, Чтение.Имя, Чтение.Значение. Сразу видно, на каком узле логика разошлась с файлом.
  • 🐞 Для DOM смотрите в отладчике Документ.ЭлементДокумента и раскрывайте дочерние узлы.
  • 🐞 Пустые узлы Текст из переводов строк и отступов — норма. Отсекайте их проверкой ПустаяСтрока(Чтение.Значение).

Если файл пришёл одной строкой без переносов, его удобно переформатировать прямо в 1С. Прочитайте его в DOM и запишите обратно с отступами:

Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл(ПутьКНовомуФайлу, Новый ПараметрыЗаписиXML("UTF-8", "1.0", Истина));
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(Документ, Запись);
Запись.Закрыть();

Третий параметр ПараметрыЗаписиXML включает отступы. Полученный файл читается глазами без внешних программ.

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

Можно ли открыть XML в 1С двойным щелчком, как Excel?
Нет. Режим «Предприятие» не связан с расширением .xml. Загружайте файл командой конфигурации или обработкой, а для просмотра используйте Конфигуратор или браузер.
Почему одна и та же обработка в файловой базе работает, а в серверной нет?
В файловой базе код «сервера» выполняется на компьютере пользователя и видит его диск. В клиент-серверной базе код идёт на сервере 1С, и путь к рабочему столу пользователя там не существует. Передавайте файл через временное хранилище.
Какой способ быстрее на файле в 500 МБ?
ЧтениеXML. Он не строит дерево в памяти. DOM и XDTO на таком объёме могут исчерпать память рабочего процесса.
Как загрузить XML из Excel-подобной таблицы в 1С?
Если внутри плоский список строк, проще открыть файл в Excel, сохранить как .xlsx и загрузить через стандартную загрузку из файла в табличную часть или справочник. Кода писать не придётся.
Нужна ли XSD-схема, чтобы прочитать файл?
Для ЧтениеXML и DOM — нет. Для XDTO с типизированным разбором и проверкой — да, её импортируют в XDTO-пакет.