Работа с механизмом XDTO (XML Data Transfer Objects) в 1С является мощным инструментом для интеграции, однако она требует строгого соблюдения стандартов W3C XML Schema. Часто программисты сталкиваются с трудночитаемыми ошибками вроде «Структура объекта не соответствует типу», даже если визуально XML-файл кажется верным. Проанализируем типичные причины возникновения таких проблем и найдем правильные способы их решения.
Одной из самых распространенных причин отказа 1С принимать схему XSD является нарушение последовательности описания свойств внутри complexType. В языке определения схем XML существует жесткое правило: все вложенные элементы (описанные через xs:sequence, xs:choice или xs:all) должны располагаться строго ДО описания атрибутов (xs:attribute).
Рассмотрим ситуацию, с которой столкнулся автор темы. В его исходной схеме атрибуты были перемешаны с последовательностью элементов или шли перед ней. Проанализируем, как должна выглядеть правильная структура на примере типа Данные:
<xs:complexType name="Данные">
<xs:sequence>
<xs:element name="Реализации" type="tns:Реализации" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="ОрганизацияИНН" type="xs:string"/>
<xs:attribute name="Дата1" type="xs:date"/>
<xs:attribute name="Дата2" type="xs:date"/>
<xs:attribute name="ВремяВыгрузки" type="xs:string"/>
</xs:complexType>
Обратите внимание: блок xs:sequence закрывается до того, как начинаются определения xs:attribute. Если вы поменяете их местами, Фабрика XDTO в 1С выдаст ошибку валидации при попытке прочитать XML-данные, так как парсер ожидает увидеть структуру в строго определенном стандартом порядке.
Выясним еще одну важную причину, по которой 1С может «не видеть» данные в файле. Это несоответствие пространств имен (Namespaces). В схеме автора указан targetNamespace="http://localhost/testXML". Это означает, что все элементы, описанные в этой схеме, принадлежат данному пространству.
Если в вашем XML-файле корневой тег выглядит просто как <Данные> без указания xmlns, то 1С не сможет сопоставить его с типом из схемы. Рассмотрим два варианта решения этой проблемы:
<Данные xmlns="http://localhost/testXML" ... >.targetNamespace из строки схемы и установите параметры elementFormDefault="unqualified".Проанализируем также атрибут elementFormDefault. Если установлено значение qualified, то все вложенные элементы (Реализации, СтрокаТЧ) также должны быть явно соотнесены с пространством имен схемы в исходном XML-файле.
В схемах XDTO важно различать Тип объекта и сам Элемент. В коде автора описаны только complexType. Однако для того, чтобы метод ПрочитатьXML сработал корректно, фабрика должна знать, какой элемент является корневым. Рекомендуется добавлять в корень схемы декларацию элемента:
<xs:element name="Данные" type="tns:Данные"/>
Без этой строки фабрика может успешно создать типы, но не «узнает» начало документа при чтении из ЧтениеXML.
Разберем ситуацию со значениями атрибутов. В примере автора атрибут ОрганизацияПлательщикНДС имеет значение "1", а тип в схеме — xs:boolean. Согласно спецификации XML, значениями для boolean могут быть true, false, 1 или 0. Однако 1С при строгой проверке иногда может требовать соответствия внутренним представлениям.
Аналогично с датами. Тип xs:date ожидает формат YYYY-MM-DD. Если в вашем файле дата передается в формате DD.MM.YY (как в поле ВремяВыгрузки в примере), то использование типа xs:date приведет к ошибке. В таких случаях используйте xs:string и преобразуйте дату программно после загрузки.
Посмотрим на пример кода, который позволит правильно загрузить данные, используя подготовленную схему. Предположим, что СтрокаXSD — это ваша выверенная строка со схемой.
// Создадим фабрику на основании схемы
ИмяФайлаСхемы = ПолучитьИмяВременногоФайла("xsd");
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(СтрокаXSD);
ТекстовыйДокумент.Записать(ИмяФайлаСхемы, КодировкаТекста.UTF8);
Модель = ФабрикаXDTO.СоздатьМодельXSD(ИмяФайлаСхемы);
МояФабрика = Новый ФабрикаXDTO(Модель);
// Читаем файл
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлуXML);
Попытка
ДанныеОбъекта = МояФабрика.ПрочитатьXML(ЧтениеXML);
// Теперь можно обращаться к свойствам: ДанныеОбъекта.ОрганизацияИНН
Исключение
Сообщить("Ошибка чтения: " + ОписаниеОшибки());
КонецПопытки;
Если при попытке валидации или чтения вы получаете сообщение «Content Is Not Allowed In Prolog», это означает, что в самом начале вашего XML-файла (до тега <?xml ...?>) находятся лишние символы. Часто это BOM (Byte Order Mark) — невидимые символы, которые добавляют некоторые текстовые редакторы при сохранении в UTF-8. При работе в 1С рекомендуется открывать файл с явным указанием кодировки или предварительно очищать строку от непечатаемых символов.
Если XML-файл имеет слишком «свободную» структуру, которая постоянно нарушает правила XSD, или если пространства имен в нем расставлены хаотично, можно рассмотреть отказ от XDTO в пользу DOM (Document Object Model). Это более гибкий, хотя и менее строгий способ.
Выясним, как это реализовать:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлуXML);
ПостроительDOM = Новый ПостроительDOM;
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
// Поиск узлов через XPath или перебором
СписокРеализаций = ДокументDOM.ПолучитьЭлементыПоИмени("Реализация");
Для Каждого УзелРеализация Из СписокРеализаций Цикл
Номер = УзелРеализация.Атрибуты.ПолучитьИмя(0).Значение; // Пример получения атрибута
// Обработка данных
КонецЦикла;
Подводя итог, отметим, что для победы над схемой XDTO необходимо:
xs:attribute всегда шли после xs:sequence.targetNamespace в схеме и xmlns в XML.Использование этих правил позволит вам избежать большинства ошибок при десериализации данных в 1С.