Работа с XDTO (XML Data Transfer Objects) в 1С часто вызывает трудности у разработчиков, особенно когда структура XML не идеально совпадает с ожидаемой XSD-схемой. Распространенные ошибки, такие как "Проверка дополнительного свойства" или "Структура объекта не соответствует типу", могут поставить в тупик даже опытного специалиста. В этой статье мы разберем основные причины возникновения этих ошибок, рассмотрим механизмы работы Фабрики XDTO и научимся правильно формировать и читать XML-файлы.
Проанализируем ситуацию, когда при выполнении метода ПрочитатьXML платформа выдает ошибку преобразования. Это происходит в тот момент, когда парсер 1С встречает в файле элемент, который не описан в свойствах типа в вашем XDTO-пакете. Рассмотрим основные причины:
<html> или <body> как данные XML, что и приводит к ошибке «Элемент имя: {».Для корректного чтения данных нам необходимо сначала определить тип объекта, который мы ожидаем получить. Выясним, как сделать это программно, используя объект ЧтениеXML. Рассмотрим пример кода для разбора ответа от веб-сервиса:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
// Пытаемся получить тип из фабрики по пространству имен и имени типа
ТипОбъекта = ФабрикаXDTO.Тип("http://www.example.com/integration", "MyResponseTypeName");
Попытка
// Читаем XML, указывая ожидаемый тип для строгой проверки
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML, ТипОбъекта);
// Перебор вложенных данных
Для каждого СтрокаДанных Из ОбъектXDTO.return.rows Цикл
Сообщить(СтрокаДанных.Name);
КонецЦикла;
Исключение
Сообщить("Ошибка чтения: " + ОписаниеОшибки());
КонецПопытки;
Важно помнить: если вы используете метод ПрочитатьXML без указания типа вторым параметром, 1С попытается определить тип автоматически по корневому элементу XML. Если в схеме этот элемент не помечен как Корневое свойство, возникнет ошибка.
Рассмотрим распространенную ошибку, когда при формировании файла теги начинают дублироваться, например, вместо <Data>1</Data> получается <Data><Data>1</Data></Data>. Проанализируем типичный ошибочный код:
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьXML.ЗаписатьНачалоЭлемента("GetInform"); // ОШИБКА: ручное создание тега
// Фабрика сама умеет записывать имя элемента
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектGetInform, "GetInform");
ЗаписьXML.ЗаписатьКонецЭлемента();
Почему это происходит? Метод ЗаписатьXML третьим параметром принимает ЛокальноеИмя. Если вы уже открыли элемент вручную через ЗаписатьНачалоЭлемента, а затем вызвали метод фабрики с тем же именем, 1С создаст вложенную структуру. Чтобы этого избежать, используйте один из двух подходов:
ЗаписатьXML, если объект должен "слиться" с текущим уровнем.Иногда сторонние разработчики предоставляют схемы с ошибками или отсутствующими параметрами. Разберем ситуацию с targetNamespace. Если в импортируемой схеме не указано пространство имен, 1С может выдать ошибку при загрузке пакета. Это так называемые "хамелеонные" схемы.
Проанализируем способы решения этой задачи:
targetNamespace="НужныйАдрес". Это позволит 1С однозначно идентифицировать типы.
НаборСхем = Новый НаборСхемXML;
НаборСхем.Добавить("C:\Schemas\BaseTypes.xsd");
НаборСхем.Добавить("C:\Schemas\MainService.xsd");
// Создаем фабрику, объединяющую несколько файлов схем
МояФабрика = Новый ФабрикаXDTO(НаборСхем);
Если объект не читается, попробуйте воспользоваться методом Проверить(). После того как вы получили ОбъектXDTO (возможно, через чтение без привязки к типу или путем ручного заполнения), вызовите этот метод. Платформа укажет на конкретное свойство, которое нарушает правила схемы.
Также стоит обратить внимание на свойство "Смешанное" (Mixed) в определении типа в пакете XDTO. Если ваш XML содержит текст между дочерними тегами, а в схеме это не разрешено, 1С выдаст ошибку валидации. Установка этого флага позволяет игнорировать лишние пробелы и текстовые узлы внутри сложных типов.
Посмотрим на ситуацию со стороны HTML-тегов еще раз. Если в процессе отладки вы видите, что ошибка происходит на символе <, обязательно проверьте содержимое переменной ЧтениеXML. С большой вероятностью вместо данных там находится текст ошибки веб-сервера. Используйте метод ЧтениеXML.Контекст() или просто сохраните поток в текстовый файл для визуального анализа перед вызовом фабрики.