При интеграции 1С с государственными информационными системами, такими как ГИС МТ «Честный ЗНАК», разработчики часто сталкиваются со специфическими XSD-схемами. Одной из распространенных проблем является отсутствие в файле схемы атрибута targetNamespace. Это ставит в тупик при попытке создать фабрику XDTO, так как непонятно, к какому пространству имен обращаться для создания объектов. Рассмотрим подробно, как решить эту задачу, правильно загрузить зависимые файлы и начать работу с данными маркировки.
Когда мы используем метод СоздатьФабрикуXDTO(ИмяФайла), платформа анализирует структуру XSD. Если в корневом элементе <xs:schema> не определен целевой URI (атрибут targetNamespace), 1С помещает все определенные в файле типы в так называемое «пустое» пространство имен. Попытка получить тип через Фабрика.Тип("http://www.w3.org/2001/XMLSchema", "acceptance") или через неопределенное пространство приведет к ошибке, так как 1С ожидает точного соответствия URI.
Ситуация осложняется наличием директивы <xs:include>. В схемах «Честного ЗНАКА» часто используется разделение: основной документ (например, приемка) описывается в одном файле, а базовые типы (ИНН, GUID, сроки) — в другом, например, LP_base_types_v2.xsd. Если загрузить только основной файл, фабрика не сможет разрешить ссылки на базовые типы.
Проанализируем первый и самый правильный с точки зрения платформы способ. Если схема не содержит targetNamespace, мы должны обращаться к ней, передавая пустую строку в качестве URI. Разберем этот процесс по шагам.
Во-первых, если файлов несколько, их необходимо загружать массивом. Это позволит 1С сопоставить include внутри файлов. Посмотрим на пример кода:
СписокФайлов = Новый Массив;
СписокФайлов.Добавить("C:\Schemas\acceptance.xsd");
СписокФайлов.Добавить("C:\Schemas\LP_base_types_v2.xsd");
Попытка
МояФабрика = СоздатьФабрикуXDTO(СписокФайлов);
Исключение
Сообщить("Ошибка создания фабрики: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Во-вторых, после создания фабрики, для получения типа acceptance, мы должны использовать пустую строку. Выясним, как это выглядит в коде:
// Правильное получение типа из схемы без targetNamespace
ТипПриемка = МояФабрика.Тип("", "acceptance");
// Создание объекта XDTO
ОбъектПриемка = МояФабрика.Создать(ТипПриемка);
Важный момент: если вы укажете Неопределено вместо "", система может не найти тип, так как для XDTO пустая строка и отсутствие значения — не всегда одно и то же при поиске в пространстве имен.
Иногда для удобства разработки или из-за особенностей интеграции с другими системами удобнее, чтобы пространство имен все же было явно задано. Рассмотрим вариант, когда мы принудительно внедряем URI в схему перед ее чтением. Это можно сделать прямо в памяти, не изменяя исходные файлы на диске.
Выполним следующие действия: прочитаем текст файла, найдем тег <xs:schema> и добавим в него атрибут targetNamespace и соответствующий xmlns. Проанализируем пример функции:
Функция ПодготовитьСхемуСПространствомИмен(ПутьКФайлу, НужныйURI)
ЧтениеТекста = Новый ЧтениеТекста(ПутьКФайлу);
ТекстСхемы = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
// Заменяем начало тега, добавляя наше пространство имен
ТекстСхемы = СтрЗаменить(ТекстСхемы,
"<xs:schema",
"<xs:schema targetNamespace=""" + НужныйURI + """ xmlns=""" + НужныйURI + """");
Возврат ТекстСхемы;
КонецФункции
Однако помните: если вы добавили targetNamespace в основной файл, вы обязаны добавить его и во все файлы, которые подключаются через include. В противном случае механизм include сломается, так как он требует совпадения пространств имен включаемого и включающего файлов. В такой ситуации лучше использовать директиву import, но это потребует более сложной переработки XSD.
Если фабрика создается, но вы не видите нужных типов, проанализируем ситуацию с помощью объекта СхемаXML. Это поможет нам увидеть, как именно 1С интерпретирует структуру файла. Разберем пример отладочного кода:
Схема = Новый СхемаXML;
Схема.ПерейтиКСодержимому(ИмяФайла);
Для Каждого ЭлементСхемы Из Схема.Элементы Цикл
Сообщить("Найден элемент: " + ЭлементСхемы.Имя + " [URI: " + ЭлементСхемы.ПространствоИмен + "]");
КонецЦикла;
Для Каждого ТипСхемы Из Схема.Типы Цикл
Сообщить("Доступен тип: " + ТипСхемы.Имя);
КонецЦикла;
Этот метод позволяет точно выяснить, под каким URI «прописались» типы в памяти 1С. Если в поле ПространствоИмен вы видите пустую строку — значит, гипотеза о пустом пространстве имен верна.
При работе с XDTO для маркировки недостаточно просто прочитать схему. Рассмотрим несколько критических нюансов, которые помогут избежать ошибок при отправке данных на сервер ЦРПТ:
<xs:sequence>. Это означает, что элементы в XML должны идти строго в том порядке, в котором они описаны в XSD. При использовании объекта XDTO 1С следит за этим сама, но если вы заполняете объект программно, старайтесь добавлять свойства последовательно.<xs:attribute name="version" fixed="5"/>. При создании объекта через Фабрика.Создать() это значение может не установиться автоматически. Всегда проверяйте наличие таких атрибутов и устанавливайте их вручную: ОбъектПриемка.version = 5;.inn_type или datetimeoffset_type. Они определены во внешнем файле LP_base_types_v2.xsd. Если вы не загрузите этот файл в массиве при создании фабрики, 1С выдаст ошибку "Тип не определен" при попытке прочитать основной файл.Проанализируем финальную последовательность действий для успешного входа в разработку под маркировку:
СоздатьФабрикуXDTO(МассивПутей)."" в качестве пространства имен.ЗаписьXML убедитесь, что вы не добавляете лишних префиксов, которые могут не понравиться парсеру системы маркировки.Соблюдение этих правил позволит вам быстро "вкатиться" в работу с маркировкой и избежать типичных ошибок при работе со сложными XSD-схемами без явно заданных пространств имен.