Как упростить обмен данными между 1С и внешними системами с помощью XDTO, EnterpriseData и XSLT

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

Интеграция систем «1С:Предприятие» со сторонним программным обеспечением (веб-сайтами, мобильными приложениями, внешними базами данных SQL) — одна из наиболее частых задач разработчика. Когда встает вопрос обмена по строгой схеме XML/JSON, стандартным инструментом выступает технология XDTO (XML Data Transfer Objects). Однако ручное описание соответствий каждого реквизита в коде превращается в рутину, а использование сложных форматов вроде EnterpriseData в нетиповых конфигурациях вызывает массу вопросов.

В этой статье мы подробно разберем, как уйти от монотонного ручного заполнения свойств XDTO, как адаптировать технологии «1С» для нетиповых конфигураций, рассмотрим современные подходы с использованием JSON и решим частую проблему с пространствами имен при XSLT-преобразованиях.

---

Метод 1. Автоматизация заполнения XDTO и уход от «ручной» работы

При использовании фабрики XDTO стандартный подход «в лоб» требует от разработчика явного присвоения каждого свойства. Если объектов десятки, а реквизитов сотни, код превращается в бесконечную простыню. Для упрощения этой задачи мы можем использовать универсальные алгоритмы обхода метаданных и свойств пакета.

Проанализируем ситуацию: физическая структура хранения данных в источнике (например, в сторонней SQL-базе) и приемнике (1С) различается, но имена полей в XML-схеме (XSD) зачастую сопоставимы с реквизитами объектов 1С или ключами структуры-источника. Мы можем написать универсальную рекурсивную функцию заполнения объекта XDTO:


Функция ЗаполнитьОбъектXDTO(ИсточникДанных, ТипXDTO) Экспорт
    
    // Создаем объект XDTO по переданному типу
    НовыйОбъектXDTO = ФабрикаXDTO.Создать(ТипXDTO);
    
    // Обходим свойства типа XDTO
    Для Каждого Свойство Из ТипXDTO.Свойства Цикл
        ИмяСвойства = Свойство.Имя;
        
        // Проверяем наличие значения в источнике (например, в Структуре или Выборке)
        ЗначениеИсточника = Неопределено;
        Если ТипЗнч(ИсточникДанных) = Тип("Структура") И ИсточникДанных.Свойство(ИмяСвойства) Тогда
            ЗначениеИсточника = ИсточникДанных[ИмяСвойства];
        ИначеЕсли Найти(ТипЗнч(ИсточникДанных), "Выборка") > 0 Тогда
            Попытка
                ЗначениеИсточника = ИсточникДанных[ИмяСвойства];
            Исключение
                Продолжить; // Свойство отсутствует в выборке
            КонецПопытки;
        КонецЕсли;
        
        Если ЗначениеИсточника = Неопределено Тогда
            Продолжить;
        КонецЕсли;
        
        // Проверяем, является ли свойство простым типом
        Если Свойство.Тип.ТипКонтекста = ТипКонтекстаXDTO.Простой Тогда
            // Если это ссылка 1С, выгружаем ее уникальный идентификатор (GUID)
            Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(ЗначениеИсточника)) 
               Или Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(ЗначениеИсточника)) Тогда
                НовыйОбъектXDTO[ИмяСвойства] = Строка(ЗначениеИсточника.УникальныйИдентификатор());
            Иначе
                НовыйОбъектXDTO[ИмяСвойства] = ЗначениеИсточника;
            EndIf;
        Иначе
            // Если свойство представляет собой вложенный объект XDTO (сложный тип)
            НовыйОбъектXDTO[ИмяСвойства] = ЗаполнитьОбъектXDTO(ЗначениеИсточника, Свойство.Тип);
        КонецЕсли;
    КонецЦикла;
    
    Возврат НовыйОбъектXDTO;
КонецФункции

Использование такого подхода сокращает объем кода интеграции на 80%. Также обратите внимание на Библиотеку стандартных подсистем (БСП). В модуле ОбменДаннымиXDTOСервер содержатся готовые функции преобразования, такие как ОбъектXDTOВСтруктуру(), которые позволяют быстро преобразовывать полученные XML-данные в привычные структуры 1С без ручного разбора дерева XML.

---

Метод 2. Адаптация EnterpriseData под нетиповые конфигурации

Существует распространенное заблуждение, что технология EnterpriseData (ED) применима только для крупных типовых решений (ERP, КА, УТ). Однако, если сторонний разработчик готов формировать файлы по стандарту EnterpriseData, вы можете развернуть этот механизм и в самописной базе.

Выясним, как это сделать с минимальными затратами:

  1. Выборочное внедрение БСП: Нет необходимости переносить всю библиотеку. Из БСП достаточно внедрить подсистему «Обмен данными», которая содержит базовые механизмы регистрации изменений, сериализации и работы с транспортными сообщениями.
  2. Использование универсальной обработки: Для разовых или простых интеграций можно использовать обработку «Выгрузка загрузка EnterpriseData». Ей можно передавать XML-строку напрямую из внешней системы.
  3. Перенос нетиповых данных и регистров сведений: Так как EnterpriseData ориентирован на объектную модель (документы и справочники), разработчики часто сталкиваются с проблемой передачи регистров сведений (например, штрихкодов или цен). Решить это можно двумя путями:
    • Передавать записи регистра внутри родительских объектов (например, передавать штрихкоды внутри объекта номенклатуры).
    • Использовать предопределенное свойство AdditionalInfo (Дополнительные сведения). Оно присутствует во всех ключевых типах EnterpriseData и имеет тип AnyType, что позволяет упаковывать туда произвольные структуры данных без изменения общей XSD-схемы.

---

Метод 3. Использование произвольных XSD-схем в Конвертации данных 3.0

Еще одно частое заблуждение заключается в том, что программа «1С:Конвертация данных 3.0» жестко привязана только к типовому EnterpriseData. Это не так.

Вы можете спроектировать собственный облегченный XSD-пакет под нужды вашей уникальной интеграции, загрузить его в КД 3.0 в качестве конфигурации-приемника или источника и визуально настроить правила конвертации объектов (ПКО) и правила обработки данных (ПОД). Это полностью избавит вас от необходимости писать код чтения/записи XML вручную на стороне 1С.

---

Метод 4. Переход с XML на JSON через механизмы XDTO

Если внешняя система разработана на современных веб-технологиях (Node.js, Python, PHP), ее разработчикам будет гораздо комфортнее работать с форматом JSON, нежели с перегруженным XML. Платформа 1С позволяет использовать настроенные пакеты XDTO для работы с JSON, сохраняя строгую типизацию схемы.

Рассмотрим пример, как быстро сериализовать объект XDTO в JSON-строку:


// Создаем запись JSON
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(,,, ЭлементыАннотацииJSON.Использовать);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);

// Записываем объект XDTO в JSON с использованием сериализатора
СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, НашОбъектXDTO, НазначениеXMLНоменклатуры.СопоставлениеТипов);

СтрокаJSON = ЗаписьJSON.Закрыть();
// СтрокаJSON готова для отправки через HTTP-запрос внешнему ПО

Внешнее ПО отправляет вам стандартный JSON, а вы на стороне 1С мгновенно восстанавливаете его в строго типизированный объект XDTO с помощью метода СериализаторXDTO.ПрочитатьJSON(). Это решает проблему валидации данных на лету.

---

Решение проблемы с XSLT: как правильно работать с пространствами имен

Часто при обмене со сторонним ПО требуется преобразовать XML из формата 1С в структуру сторонней системы (или наоборот). Для этого применяется технология XSLT-преобразований. На практике разработчики часто сталкиваются с ситуацией, когда шаблон XSLT не находит элементы в исходном XML (например, уникальный идентификатор Ref или пометку удаления DeletionMark), возвращая пустой результат.

Выясним причину этой проблемы. Рассмотрим пример исходного XML-файла:


<?xml version="1.0" encoding="utf-8"?>
<DocumentObject.ЗаказПокупателя xmlns="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Ref>377b50c4-edf5-11e6-9306-0cc47a067dfb</Ref>
  <DeletionMark>false</DeletionMark>
</DocumentObject.ЗаказПокупателя>

Обратите внимание на атрибут xmlns="http://v8.1c.ru/8.1/data/enterprise/current-config". Он задает пространство имен по умолчанию. Согласно спецификации XPath 1.0 (которая используется процессором 1С), любые элементы в XML, находящиеся внутри пространства имен по умолчанию, не могут быть выбраны в XPath-выражениях по их простому имени (например, через select="./Ref") без явного указания префикса.

Для успешного преобразования нам необходимо явно объявить префикс пространства имен 1С в самом XSL-шаблоне и использовать его при выборке узлов. Разберем правильный, рабочий шаблон преобразования:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:v8="http://v8.1c.ru/8.1/data/enterprise/current-config"
    exclude-result-prefixes="v8">
    
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
     
    <!-- Шаблон для корневого узла -->
    <xsl:template match="/">
        <xsl:apply-templates select="v8:DocumentObject.ЗаказПокупателя"/>
    </xsl:template>
     
    <!-- Шаблон преобразования документа -->
    <xsl:template match="v8:DocumentObject.ЗаказПокупателя">
        <DocumentObject.Задание xmlns="http://v8.1c.ru/8.1/data/enterprise/current-config" 
                                xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            
            <!-- Выбираем элементы, обязательно используя префикс v8 -->
            <xsl:copy-of select="v8:Ref" />
            <xsl:copy-of select="v8:DeletionMark" />
            
            <!-- Добавляем новые статические или расчетные узлы -->
            <Date>2017-02-08T14:53:14</Date>
            
        </DocumentObject.Задание>
    </xsl:template>
</xsl:stylesheet>

Использование директивы exclude-result-prefixes="v8" гарантирует, что временный префикс v8 не перейдет в результирующий XML-файл, благодаря чему мы получим чистую и валидную структуру на выходе.

Применяя данные подходы, мы переводим интеграцию на качественно новый уровень: уходим от ручного написания кода парсинга, повышаем отказоустойчивость обменов и обеспечиваем простоту интеграции со сторонними разработчиками.

← На главную