Как сформировать XML-файл с пространствами имен и несколькими атрибутами в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С со сторонними системами (такими как Microsoft Dynamics AX / Axapta, Navision или кастомными ERP-решениями) разработчики часто сталкиваются с жесткими требованиями к формату выгрузки. Например, XML-документ должен содержать префиксы пространств имен (например, Table:Record, Table:Field), специфическую кодировку windows-1251 и множество атрибутов у одного узла.

Разберем основные подходы к решению этой задачи: использование потоковых объектов 1С, работу со встроенным механизмом ДокументDOM и исправление типичных ошибок при работе через COM-объект MSXML.

Вариант 1. Оптимальный потоковый метод через объекты «ЗаписьXML» и «ЧтениеXML»

Часто разработчики считают, что объект ЗаписьXML не способен создавать префиксы и атрибуты, однако это заблуждение. Потоковая запись является наиболее производительным и кроссплатформенным решением (работает как под Windows, так и под Linux), практически не расходует оперативную память при выгрузке сотен тысяч записей.

Рассмотрим по шагам, как сформировать требуемую структуру с префиксом Table: и несколькими атрибутами:

  1. Инициализируем объект ЗаписьXML и открываем файл с кодировкой windows-1251.
  2. Записываем объявление XML и связываем префикс пространства имен с помощью метода ЗаписатьСоответствиеПространствИмен.
  3. Формируем узлы методом ЗаписатьНачалоЭлемента, передавая локальное имя и URI пространства имен — платформа автоматически подставит нужный префикс.
  4. Добавляем требуемое количество атрибутов последовательными вызовами ЗаписатьАтрибут.

Посмотрим на пример формирования файла:


ПутьКФайлу = "C:\export.xml";
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ПутьКФайлу, "windows-1251");

ЗаписьXML.ЗаписатьОбъявлениеXML();

// Корневой элемент с объявлением пространств имен
ЗаписьXML.ЗаписатьНачалоЭлемента("AxaptaXMLExport", "urn:http://www.navision.com/Formats/Table1");
ЗаписьXML.ЗаписатьСоответствиеПространствИмен("Table", "urn:http://www.navision.com/Formats/Table");
ЗаписьXML.ЗаписатьАтрибут("version", "1.0");

// Вложенный узел транзакции
ЗаписьXML.ЗаписатьНачалоЭлемента("transaction");
ЗаписьXML.ЗаписатьАтрибут("version", "1.0");

// Формирование строк выгрузки
Для Счетчик = 1 По 10 Цикл
    // Платформа автоматически сформирует тег <Table:Record> благодаря указанию URI
    ЗаписьXML.ЗаписатьНачалоЭлемента("Record", "urn:http://www.navision.com/Formats/Table");
    ЗаписьXML.ЗаписатьАтрибут("name", "InventTableExportDC");
    ЗаписьXML.ЗаписатьАтрибут("row", Строка(Счетчик));
    
    // Вложенное поле
    ЗаписьXML.ЗаписатьНачалоЭлемента("Field", "urn:http://www.navision.com/Formats/Table");
    ЗаписьXML.ЗаписатьАтрибут("name", "ManDate");
    ЗаписьXML.ЗаписатьТекст("123");
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Field
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Record
КонецЦикла;

ЗаписьXML.ЗаписатьКонецЭлемента(); // transaction
ЗаписьXML.ЗаписатьКонецЭлемента(); // AxaptaXMLExport

ЗаписьXML.Закрыть();

Для обратного чтения такого файла используем объект ЧтениеXML. Проанализируем пример обхода:


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);

Пока ЧтениеXML.Прочитать() Цикл
    Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.ЛокальноеИмя = "Record" Тогда
        ИмяТаблицы = ЧтениеXML.ПолучитьАтрибут("name");
        НомерСтроки = ЧтениеXML.ПолучитьАтрибут("row");
    ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.ЛокальноеИмя = "Field" Тогда
        ИмяПоля = ЧтениеXML.ПолучитьАтрибут("name");
        ЧтениеXML.Прочитать(); // переходим к тексту внутри тега
        ЗначениеПоля = ЧтениеXML.Значение;
    КонецЕсли;
КонецЦикла;

ЧтениеXML.Закрыть();

Вариант 2. Работа через встроенный объект «ДокументDOM»

Если требуется формировать или модифицировать XML в виде объектной модели в оперативной памяти без использования сторонних библиотек, рекомендуется использовать встроенную объектную модель ДокументDOM.

Рассмотрим реализацию через объектную модель 1С:


ДокументDOM = Новый ДокументDOM;

// Создание корневого элемента
КорневойУзел = ДокументDOM.СоздатьЭлементNS("urn:http://www.navision.com/Formats/Table1", "AxaptaXMLExport");
КорневойУзел.УстановитьАтрибут("version", "1.0");
КорневойУзел.УстановитьАтрибут("xmlns:Table", "urn:http://www.navision.com/Formats/Table");
ДокументDOM.ВставитьДо(КорневойУзел, Неопределено);

УзелТранзакции = ДокументDOM.СоздатьЭлемент("transaction");
УзелТранзакции.УстановитьАтрибут("version", "1.0");
КорневойУзел.ДобавитьДочерний(УзелТранзакции);

Для Счетчик = 1 По 10 Цикл
    УзелЗаписи = ДокументDOM.СоздатьЭлементNS("urn:http://www.navision.com/Formats/Table", "Table:Record");
    УзелЗаписи.УстановитьАтрибут("name", "InventTableExportDC");
    УзелЗаписи.УстановитьАтрибут("row", Строка(Счетчик));
    УзелТранзакции.ДобавитьДочерний(УзелЗаписи);
    
    УзелПоля = ДокументDOM.СоздатьЭлементNS("urn:http://www.navision.com/Formats/Table", "Table:Field");
    УзелПоля.УстановитьАтрибут("name", "ManDate");
    УзелПоля.ТекстовоеСодержимое = "123";
    УзелЗаписи.ДобавитьДочерний(УзелПоля);
КонецЦикла;

// Запись DOM-документа в файл
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\export_dom.xml", "windows-1251");
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(ДокументDOM, ЗаписьXML);
ЗаписьXML.Закрыть();

Вариант 3. Использование COM-объекта MSXML и исправление частых ошибок

При формировании структуры через MSXML.DOMDocument частой ошибкой является попытка передачи дополнительных атрибутов через свойство text. В результате в файл попадает некорректный синтаксис вида <Table:Record name="InventTableExportDC">row="1"</Table:Record>.

Выясним причину: каждый атрибут должен добавляться отдельным вызовом метода setAttribute у созданного узла.

Посмотрим на исправленный код работы с COM-объектом:


XMLDOM = Новый COMОбъект("MSXML2.DOMDocument");
XMLDOM.async = 0;
XMLDOM.validateOnParse = 0;
XMLDOM.resolveExternals = 0;

// Добавление заголовка
Инструкция = XMLDOM.createProcessingInstruction("xml", "version=""1.0"" encoding=""windows-1251""");
XMLDOM.appendChild(Инструкция);

// Корневой узел
КорневойЭлемент = XMLDOM.createElement("AxaptaXMLExport");
КорневойЭлемент.setAttribute("xmlns:Table", "urn:http://www.navision.com/Formats/Table");
КорневойЭлемент.setAttribute("version", "1.0");
XMLDOM.appendChild(КорневойЭлемент);

Транзакция = XMLDOM.createElement("transaction");
Транзакция.setAttribute("version", "1.0");
КорневойЭлемент.appendChild(Транзакция);

Для Счетчик = 1 По 10 Цикл
    СтрокаЗаписи = XMLDOM.createElement("Table:Record");
    // Установка нескольких атрибутов узла
    СтрокаЗаписи.setAttribute("name", "InventTableExportDC");
    СтрокаЗаписи.setAttribute("row", Счетчик);
    Транзакция.appendChild(СтрокаЗаписи);
    
    СтрокаПоля = XMLDOM.createElement("Table:Field");
    СтрокаПоля.setAttribute("name", "ManDate");
    СтрокаПоля.text = "123";
    СтрокаЗаписи.appendChild(СтрокаПоля);
КонецЦикла;

XMLDOM.Save("C:\export_msxml.xml");

Важное ограничение: Использование COM-объектов привязано исключительно к операционной системе Windows. Если сервер 1С функционирует на базе Linux или требуется высокая скорость обработки больших массивов данных, следует отдавать предпочтение объектам ЗаписьXML и ЧтениеXML.

← На главную