При интеграции 1С со сторонними системами (такими как Microsoft Dynamics AX / Axapta, Navision или кастомными ERP-решениями) разработчики часто сталкиваются с жесткими требованиями к формату выгрузки. Например, XML-документ должен содержать префиксы пространств имен (например, Table:Record, Table:Field), специфическую кодировку windows-1251 и множество атрибутов у одного узла.
Разберем основные подходы к решению этой задачи: использование потоковых объектов 1С, работу со встроенным механизмом ДокументDOM и исправление типичных ошибок при работе через COM-объект MSXML.
Часто разработчики считают, что объект ЗаписьXML не способен создавать префиксы и атрибуты, однако это заблуждение. Потоковая запись является наиболее производительным и кроссплатформенным решением (работает как под Windows, так и под Linux), практически не расходует оперативную память при выгрузке сотен тысяч записей.
Рассмотрим по шагам, как сформировать требуемую структуру с префиксом Table: и несколькими атрибутами:
ЗаписьXML и открываем файл с кодировкой windows-1251.ЗаписатьСоответствиеПространствИмен.ЗаписатьНачалоЭлемента, передавая локальное имя и URI пространства имен — платформа автоматически подставит нужный префикс.ЗаписатьАтрибут.Посмотрим на пример формирования файла:
ПутьКФайлу = "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.Закрыть();
Если требуется формировать или модифицировать 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.Закрыть();
При формировании структуры через 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.