Как правильно использовать метод ОбъектXDTO.Установить() по выражению XPath в 1С?

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

Коллеги-разработчики, иногда официальная документация может вводить в заблуждение или быть неполной. Именно с такой ситуацией мы столкнулись, когда речь зашла о методе Установить() объекта ОбъектXDTO платформы 1С по выражению XPath. На первый взгляд, синтаксис, описанный в справке, кажется нелогичным, поскольку отсутствует параметр для устанавливаемого значения. Однако, как показали практические эксперименты и обсуждения на форумах, реальное использование этого метода несколько отличается от заявленного. Давайте вместе разберемся, как правильно работать с этим мощным инструментом для управления данными XDTO.

Недопонимание в документации: скрытый параметр значения

В начале пути многие из нас, обращаясь к синтаксису метода Установить() для варианта по выражению XPath, обнаруживают лишь один параметр — Выражение:

Установить(<Выражение>)

Естественно возникает вопрос: куда же указывать значение, которое мы хотим установить? Этот вопрос стал отправной точкой для нашего обсуждения. Оказалось, что это недопонимание связано с неполным или некорректным описанием в справке. На практике, метод Установить() при использовании XPath-выражения всегда требует второй параметр — само устанавливаемое значение.

Если мы попробуем вызвать метод с одним параметром для примитивного XDTO-объекта, например, ОбъектXDTO.Установить("ИмяСвойства"), платформа 1С выдаст ошибку, сообщая о "недостаточно фактических параметров". Это прямое подтверждение того, что второй параметр необходим, и документация в данном случае оказалась неточной, вводя разработчиков в заблуждение.

Правильный синтаксис и базовое использование метода Установить() по выражению XPath

Итак, давайте разберем правильный и работающий синтаксис метода Установить() при использовании XPath выражения. Он соответствует общему подходу платформы 1С к методам установки значений, где всегда указывается как путь к свойству, так и само значение.

ОбъектXDTO.Установить(<Выражение>, <Значение>)

  1. <Выражение> (обязательный параметр): Это строка, которая содержит XPath-выражение. Оно служит для точного определения свойства внутри текущего объекта XDTO, значение которого необходимо изменить или установить. XPath позволяет нам навигироваться по иерархии свойств объекта.
  2. <Значение> (обязательный параметр): Это собственно то значение, которое мы хотим присвоить указанному свойству. Тип этого значения может быть достаточно гибким. Мы можем передать в качестве значения другой объект ОбъектXDTO, специальный объект ЗначениеXDTO, представляющий примитивные типы (строки, числа, даты, булевы), или даже Неопределено, если мы хотим сбросить значение свойства (с учетом определенных условий, о которых мы поговорим далее). Платформа автоматически выполняет преобразование типов, если это возможно и разрешено схемой XDTO.

Посмотрим на простой пример, чтобы понять, как это работает на практике. Допустим, у нас есть уже созданный XDTO-объект с простым свойством "ИмяСвойства" примитивного типа (например, строка). Чтобы установить ему новое значение, мы будем использовать следующий код:


// Предположим, у нас есть ФабрикаXDTO и уже определенный тип XDTO
// Например, тип "МойТипXDTO" из пространства имен "http://www.example.com"
// И этот тип имеет свойство "ИмяСвойства" строкового типа.
МойОбъектXDTO = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("http://www.example.com", "МойТипXDTO"));

// Устанавливаем значение для простого свойства по XPath
МойОбъектXDTO.Установить("ИмяСвойства", "НовоеЗначениеСвойстваДляПростогоПоля");

// Теперь мы можем проверить, что значение установилось.
// Для получения значения также можно использовать XPath.
Сообщить("Значение 'ИмяСвойства': " + МойОбъектXDTO.Получить("ИмяСвойства"));
// Вывод в окне сообщений: "Значение 'ИмяСвойства': НовоеЗначениеСвойстваДляПростогоПоля"

Этот пример демонстрирует базовый, но очень важный принцип: несмотря на расхождения с документацией, метод Установить() с XPath-выражением функционирует как ожидается, принимая два аргумента – путь и значение. Он позволяет легко и интуитивно управлять данными XDTO, особенно когда речь идет о модификации конкретного свойства.

Работа с вложенными структурами и особенности XPath-выражений в 1С

Одним из ключевых преимуществ использования XPath является возможность легкой навигации по сложным, вложенным структурам XDTO-объектов. Метод Установить() прекрасно справляется с этой задачей, позволяя нам адресоваться к свойствам, находящимся глубоко в иерархии объектов.

Представим, что наш XDTO-объект имеет вложенную структуру типов. Например, основной объект содержит свойство "ИмяСвойства1", которое само является XDTO-объектом, и этот вложенный объект, в свою очередь, содержит свойство "ИмяСвойства2" примитивного типа (например, строка). Чтобы установить значение для "ИмяСвойства2", используя XPath, мы можем указать полный путь к нему, используя символ слеша ("/").


// Создаем XDTO-объект с вложенной структурой
// Определим два типа: "ВложенныйТип" и "ОсновнойТип".
// Предположим, "ОсновнойТип" имеет свойство "ИмяСвойства1" типа "ВложенныйТип".
// А "ВложенныйТип" имеет свойство "ИмяСвойства2" примитивного типа (например, строка).

ТипВложенный = ФабрикаXDTO.Тип("http://www.example.com", "ВложенныйТип");
ТипОсновной = ФабрикаXDTO.Тип("http://www.example.com", "ОсновнойТип");

// Создаем основной XDTO-объект
МойОбъектXDTO = ФабрикаXDTO.Создать(ТипОсновной);

// Важно: если вложенный объект еще не создан, его нужно создать и установить.
// Иначе путь "ИмяСвойства1/ИмяСвойства2" будет некорректным, так как "ИмяСвойства1" пусто.
Если МойОбъектXDTO.Получить("ИмяСвойства1") = Неопределено Тогда
    МойОбъектXDTO.Установить("ИмяСвойства1", ФабрикаXDTO.Создать(ТипВложенный));
КонецЕсли;

// Устанавливаем значение для вложенного свойства с использованием XPath
МойОбъектXDTO.Установить("ИмяСвойства1/ИмяСвойства2", "ЗначениеДляВложенногоПоля");

// Проверяем результат, получая значение через вложенные вызовы Получить()
Сообщить("Значение 'ИмяСвойства1/ИмяСвойства2': " + МойОбъектXDTO.Получить("ИмяСвойства1").Получить("ИмяСвойства2"));
// Вывод: "Значение 'ИмяСвойства1/ИмяСвойства2': ЗначениеДляВложенногоПоля"

Как видите, использование символа "/" (слеш) позволяет нам строить путь к нужному свойству, проходя через иерархию объектов. Также поддерживаются относительно простые XPath-выражения, такие как "." для ссылки на текущий узел или ".." для ссылки на родительский узел, хотя в контексте метода Установить(), когда мы начинаем с корневого XDTO-объекта, чаще всего используются прямые пути от корня.

Однако важно понимать, что XPath в 1С не является полной реализацией стандарта XPath. Как отмечают разработчики 1С и подтверждают обсуждения, это "не совсем XPath, а скорее несколько модифицированное подмножество XPath". Это накладывает определенные ограничения, которые необходимо учитывать при разработке:

  1. Ограниченная навигация: В основном, XPath в 1С используется для построения пути к конкретному свойству. Он оперирует данными только внутри текущего объекта XDTO, от которого был вызван метод. Он не предназначен для запросов по всему XDTO-документу или для сложных фильтраций.
  2. Один результат: Выражения XPath в 1С, используемые с ОбъектXDTO.Установить(), предназначены для указания на одно единственное свойство. Вы не сможете использовать XPath-выражения, которые возвращают множественные узлы (например, `//ИмяСвойства2` для поиска всех свойств с таким именем в любом месте или `Свойство[1]` для выбора элемента по индексу), чтобы установить сразу несколько значений или выбрать элемент из списка. Такие конструкции просто не будут работать или приведут к ошибке выполнения. Цель метода — точечное изменение конкретного свойства.
  3. Поддерживаемые конструкции: В качестве шага пути выступает имя свойства. Также поддерживаются предопределенные конструкции . (ссылка на текущий узел) и .. (ссылка на родительский узел), которые могут быть полезны в более сложных сценариях обхода, хотя их применение для Установить(), начинающегося с корневого объекта, встречается реже. Атрибуты, условия с предикатами (например, [@Атрибут="Значение"]) и другие более сложные функции XPath обычно не поддерживаются или работают ограниченно в контексте ОбъектXDTO.Установить().

Понимание этих ограничений критически важно для эффективного использования XPath с XDTO-объектами в 1С, предотвращая попытки использовать функциональность, которая не была реализована.

Важные аспекты и правила при установке значений XDTO

При работе с методом Установить() и XDTO-объектами в целом, необходимо учитывать несколько критически важных правил и особенностей, которые влияют на успешность операции и предотвращают потенциальные ошибки. Эти правила помогают поддерживать целостность данных в соответствии с XDTO-схемой.

  1. Проверка типов значений:

    Платформа 1С осуществляет строгую проверку типов при попытке присвоить значение свойству XDTO-объекта. Это означает, что не любое значение может быть присвоено любому свойству. Значение будет успешно присвоено только в следующих случаях:

    • Его тип полностью совпадает с типом свойства, определенным в схеме XDTO. Например, если свойство имеет тип "Строка", мы можем присвоить ему строковое значение.
    • Его тип является унаследованным от типа свойства (то есть, устанавливаемое значение является экземпляром типа-наследника). Это позволяет соблюдать принципы полиморфизма в XDTO.
    • Его тип является одним из типов, входящих в объединение (union), если тип свойства определен в схеме как объединение нескольких возможных типов. В этом случае платформа попытается найти совместимый тип в списке объединения.

    Если тип устанавливаемого значения несовместим с типом свойства по этим правилам, платформа вызовет исключение. Эта проверка помогает поддерживать целостность данных в соответствии с определенной XDTO-схемой и предотвращает запись некорректных данных.

    // Пример несовместимости типов // Предположим, свойство "Количество" в XDTO-схеме имеет тип "Целое", // а мы пытаемся установить ему строковое значение. МойОбъектXDTO.Установить("Количество", "Сто"); // Этот вызов спровоцирует исключение // "Ошибка преобразования значения XDTO" или подобное, // так как "Сто" не может быть преобразовано в "Целое". // Корректное присвоение МойОбъектXDTO.Установить("Количество", 100); // Этот вызов будет успешным.

  2. Работа со свойствами, допускающими множество значений (коллекции):

    В XDTO-схемах свойства могут быть определены таким образом, что они допускают хранение более одного значения. Это обозначается как ВерхняяГраница > 1 (или maxOccurs="unbounded" в XML-схеме). Такие свойства фактически представляют собой коллекции или списки значений. Для свойств-коллекций метод Установить() не предназначен и его использование приведет к вызову исключения.

    Если вам нужно работать со свойством, которое является коллекцией (т.е. может содержать несколько значений), все операции по добавлению, изменению или удалению значений должны производиться через специальный объект — СписокXDTO. Этот список значений коллекции можно получить с помощью метода Получить() для данного свойства. Например:

    // Предположим, свойство "ЭлементыСписка" допускает множество значений (ВерхняяГраница > 1) // И каждый элемент списка имеет тип "ТипЭлемента", содержащий свойство "Имя". // Получаем объект СписокXDTO для свойства "ЭлементыСписка" СписокЭлементов = МойОбъектXDTO.Получить("ЭлементыСписка"); // Добавляем новый элемент в коллекцию через метод Добавить() объекта СписокXDTO НовыйЭлемент1 = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("http://www.example.com", "ТипЭлемента")); НовыйЭлемент1.Установить("Имя", "ПервыйЭлемент"); СписокЭлементов.Добавить(НовыйЭлемент1); НовыйЭлемент2 = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("http://www.example.com", "ТипЭлемента")); НовыйЭлемент2.Установить("Имя", "ВторойЭлемент"); СписокЭлементов.Добавить(НовыйЭлемент2); // Или изменяем существующий элемент коллекции, обращаясь к нему по индексу Если СписокЭлементов.Количество() > 0 Тогда СписокЭлементов.Получить(0).Установить("Имя", "ИзмененныйПервыйЭлемент"); КонецЕсли; // Удаляем элемент из коллекции Если СписокЭлементов.Количество() > 1 Тогда СписокЭлементов.Удалить(1); // Удаляем второй элемент КонецЕсли; Сообщить("Количество элементов после операций: " + СписокЭлементов.Количество());

    Важно: Не пытайтесь использовать Установить() непосредственно для свойств, являющихся списками или коллекциями. Это фундаментальное правило при работе с XDTO-коллекциями, его нарушение приведет к ошибкам выполнения.

  3. Присваивание Неопределено и свойство ВозможноПустое:

    Мы можем присвоить свойству значение Неопределено. Это действие фактически "обнуляет" свойство, указывая на отсутствие конкретного значения. Однако это возможно только в том случае, если свойство в XDTO-схеме разрешает пустое значение, то есть его атрибут ВозможноПустое (аналог nillable="true" в XML-схеме) установлен в Истина. Если же ВозможноПустое равно Ложь (nillable="false"), а вы пытаетесь присвоить Неопределено, будет выдано исключение.

    Используйте этот механизм осознанно, чтобы избежать ошибок и соблюдать ограничения схемы. Это особенно важно при сериализации XDTO-объектов в XML, где "пустое" значение может быть представлено по-разному в зависимости от схемы.

  4. Запрет циклических ссылок:

    При работе с объектами XDTO и ссылками между ними крайне важно помнить о запрете циклических ссылок. Цепочки ссылок на объекты XDTO, содержащиеся в свойствах других объектов, не могут образовывать циклов. Если вы попытаетесь присвоить ссылку таким образом, что это приведет к образованию цикла (например, ОбъектА ссылается на ОбъектБ, который в свою очередь ссылается на ОбъектА), платформа 1С вызовет исключение. Это ограничение служит для предотвращения бесконечных рекурсий, проблем с сериализацией/десериализацией XDTO и поддержания древовидной структуры данных.

    // Пример гипотетической ситуации, которая вызовет исключение // ОбъектXDTO_A.Установить("СсылкаНаB", ОбъектXDTO_B); // ОбъектXDTO_B.Установить("СсылкаНаA", ОбъектXDTO_A); // Здесь будет исключение о циклической ссылке

  5. Сброс значения свойства с помощью метода Сбросить():

    Если вам нужно не просто присвоить Неопределено, а именно "сбросить" свойство до его начального, неустановленного состояния (как если бы оно никогда не было задано), используйте метод Сбросить(). Этот метод также имеет два варианта синтаксиса, аналогичных Установить(): по выражению XPath и по объекту СвойствоXDTO.

    // Предположим, свойство "ИмяСвойства" имеет некое значение МойОбъектXDTO.Установить("ИмяСвойства", "Какое-то значение"); Сообщить("Установлено? " + МойОбъектXDTO.Установлено("ИмяСвойства")); // Выведет Истина // Сброс значения свойства по XPath МойОбъектXDTO.Сбросить("ИмяСвойства"); // После сброса метод Установлено() для этого свойства вернет Ложь Сообщить("Установлено после сброса? " + МойОбъектXDTO.Установлено("ИмяСвойства")); // Выведет Ложь

    Метод Сбросить() полезен, когда вы хотите явно указать, что свойство не имеет значения, и оно должно быть исключено из XML-представления при сериализации (если это позволяет схема), в отличие от присвоения Неопределено, которое может быть сериализовано как xsi:nil="true".

Заключение

Мы выяснили, что метод ОбъектXDTO.Установить() при использовании XPath-выражения в платформе 1С, несмотря на особенности документации, является мощным и вполне логичным инструментом. Главное — помнить о его корректном синтаксисе с двумя параметрами (XPath-выражение и устанавливаемое значение) и учитывать ограничения XPath-выражений в 1С, а также правила работы с типами, коллекциями и циклическими ссылками. Владение этим методом значительно упрощает манипуляции с данными XDTO, особенно в сложных иерархических структурах, и позволяет эффективно взаимодействовать с внешними системами через XDTO-объекты.

Надеемся, что этот подробный разбор поможет вам избежать затруднений и эффективно использовать объекты XDTO в ваших разработках на платформе 1С, делая ваш код более надежным и соответствующим стандартам XDTO-схем.

← На главную