Работа с XML и WEB-Сервисами

Приведение типа даты ({http://www.w3.org/2001/XMLSchema}dateTime) к формату 1С (из статьи выше)

ТипДаты = ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema", "dateTime");
ЗначениеXDTO = ФабрикаXDTO.Создать(типДаты, Строка.CursDate);
Дата1С = ЗначениеXDTO.Значение;

ФабрикаXDTO - Создает Объекты XDTO и записывает их в XML. Читает XML и создает из него Объекты XDTO.

СериализаторXDTO - Читает Объекты XDTO и превращает их в объекты встроенного языка 1С. Выполняет обратную операцию преобразования объекта встроенного языка в Объект XDTO.

ФабрикаXDTO ничего не знает о метаданных конфигурации, и вообще о конфигурации. Для нее нет ни ссылок, ни таблиц значений, ничего, связанного с прикладными типами среды исполнения 1С. Фабрика оперирует только XML-типами. Эти типы похожи на «родные» и их легко спутать, т.к. они описывают те же самые объекты, но в терминах XML. Тем не менее, важно понимать, что это именно разные объекты. XML-документ, содержащий таблицу значений и универсальная коллекция ТаблицаЗначений - это разные вещи. Фабрика знает только про XML.

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

1с через XDTO работает не со всякими схемами, если схема загружается в конфигураторе в XDTO-пакет, значит работать с ней можно.

Простые типы XML представляются в виде объектов языка 1С с типом “ЗначениеXDTO”. Составные типы XML представляются в виде объектов языка 1С с типом “ОбъектXDTO”.


Моя статья "Краткое описание создания XML файла по XSD схеме на примере создания выгрузки Статистической отчетности для ФТС"


Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
ФайлXML = Новый ЗаписьXML();
ФайлXML.ОткрытьФайл("ПутьКФайлуXML");
Сериализатор.ЗаписатьXML(ФайлXML, Объект1С);
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
ФайлXML = Новый ЧтениеXML();
ФайлXML.ОткрытьФайл("ПутьКФайлуXML");
Объект1С = Сериализатор.ПрочитатьXML(ФайлXML);

СправочникКонтрагенты_ОбъектXDTO = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "CatalogObject.Контрагенты"));
ЗаполнитьЗначенияСвойств(СправочникКонтрагенты_ОбъектXDTO, Справочники.Контрагенты.СоздатьЭлемент());
СправочникКонтрагенты_ОбъектXDTO.Description = "Некое наименование";
СправочникКонтрагенты_ОбъектXDTO.НаименованиеПолное = "Полное имя";
ФайлXML = Новый ЗаписьXML();
ФайлXML.ОткрытьФайл("ПутьКФайлуXML");
ФабрикаXDTO.ЗаписатьXML(ФайлXML, СправочникКонтрагенты_ОбъектXDTO);

Статья DmitrO с itland.ru "Перенос данных из одной конфигурации в другую отличную конфигурацию."

Обработка иллюстрирующая перенос объектов (спр.Валюты), записанных в отправителе по схеме конфигурации-получателя. И, затем, дальнейшее их пообъектное чтение из файла в получателе с записью в базу через механизм сериализации.

Объекты записаны списком с разделителем

"<разделитель>"

и читаются при загрузке блоками с помощью:

СтрокаТекста = ЧтениеТекста.ПрочитатьСтроку("<разделитель>");

Создание фабрики XDTO из схемы XSD (текстовая переменная "XSD")

	ЧтениеСхемыXML = Новый ЧтениеXML;
	ЧтениеСхемыXML.УстановитьСтроку(XSD);
	
	ПостроительDOM = Новый ПостроительDOM;
	ДокументDOM = ПостроительDOM.Прочитать(ЧтениеСхемыXML);
	
	ПостроительСхемXML = Новый ПостроительСхемXML;
	СхемаXML = ПостроительСхемXML.СоздатьСхемуXML(ДокументDOM);
	
	НаборСхемXML = Новый НаборСхемXML;
	НаборСхемXML.Добавить(СхемаXML);
	
	МояФабрикаXDTO = Новый ФабрикаXDTO(НаборСхемXML);

Другой способ создания фабрики XDTO из схемы XSD (текстовая переменная "XSD")

	ПолноеИмяВременногоФайлаXSD = КаталогВременныхФайлов() + "MyTemp.xsd";
	ЗаписьТекста = Новый ЗаписьТекста(ПолноеИмяВременногоФайлаXSD);
	ЗаписьТекста.Записать(XSD);
	ЗаписьТекста.Закрыть();
	МассивСхемXSD = Новый Массив;
	МассивСхемXSD.Добавить(ПолноеИмяВременногоФайлаXSD);
	МояФабрикаXDTO = СоздатьФабрикуXDTO(МассивСхемXSD);

Выгрузка списка полученных запросом объектов из базы в XML (текстовая переменная "XML", в схеме для Фабрики XDTO созданы типы "Объект" и "СписокОбъектов")

	МойТипВыгружаемогоОбъекта = МояФабрикаXDTO.Тип("http://wiki.katkov-a.ru", "Объект");
	МойТипСпискаВыгружаемыхОбъектов = МояФабрикаXDTO.Тип("http://wiki.katkov-a.ru", "СписокОбъектов");
	
	СписокОбъектовXDTO = МояФабрикаXDTO.Создать(МойТипСпискаВыгружаемыхОбъектов);
	
	Пока Выборка.Следующий() Цикл
		
		ОбъектИзБазы = Выборка.Ссылка.ПолучитьОбъект();
		
		ОбъектXDTO = МояФабрикаXDTO.Создать(МойТипВыгружаемогоОбъекта);
                  // Объект надо создавать каждый раз при добавлении
                  // Нельзя один раз создать Объект, а потом "вставлять" его несколько раз
                  // Объект будет "мигрировать"
                  
                  	ЗаполнитьЗначенияСвойств(ОбъектXDTO, ОбъектИзБазы);
		
		СписокОбъектовXDTO.Объект.Добавить(ОбъектXDTO);
		
	КонецЦикла;
	
	МояЗаписьXML = Новый ЗаписьXML;
	МояЗаписьXML.УстановитьСтроку();
	МояЗаписьXML.ЗаписатьОбъявлениеXML();
	МояФабрикаXDTO.ЗаписатьXML(МояЗаписьXML, СписокКонтрагеновXDTO, , , , НазначениеТипаXML.Явное);
	XML = МояЗаписьXML.Закрыть();

Загрузка XML (текстовая переменная "XML", в схеме для Фабрики XDTO созданы типы "Объект" и "СписокОбъектов")

	МойТипСпискаЗагружаемыхОбъектов = МояФабрикаXDTO.Тип("http://wiki.katkov-a.ru", "СписокОбъектов");
	
	МойXML = Новый ЧтениеXML; 
	МойXML.УстановитьСтроку(XML);
	
	Попытка
		СписокОбъектов = МояФабрикаXDTO.ПрочитатьXML(МойXML, МойТипСпискаЗагружаемыхОбъектов);
		
		Для каждого ТекОбъект Из СписокОбъектов.Объект Цикл
		
			// . . . обрабатываем ТекОбъект
			
		КонецЦикла; 
	Исключение
		Сообщение = Новый СообщениеПользователю;
		Сообщение.Текст = "Не удалось прочитать XML. " + ОписаниеОшибки();
		Сообщение.Сообщить(); 
	КонецПопытки; 
	
	МойXML.Закрыть();

Свою фабрику XDTO можно также создать непосредственно из файла схемы

	ФайлыXSD = Новый Массив();
	ФайлыXSD.Добавить(ПолноеИмяФайлаСхемыXSD);
	МояФабрикаXDTO = СоздатьФабрикуXDTO(ФайлыXSD);

процедура создания временного файла, содержащего текст XSD

Функция ПолучитьВременныйФайлСоСжемойXSD()

	ПолноеИмяФайла = КаталогВременныхФайлов() + "schema.xsd";
	ЗаписьТекста = Новый ЗаписьТекста(ПолноеИмяФайла);
	ЗаписьТекста.Записать(ТекстСхемыXSD);

	Возврат ПолноеИмяФайла;

КонецФункции

Если мы создаем ОбъектXDTO из XML файла вслепую (не используя XSD и, следовательно, Фабрика не знает, что там в ОбъектеXDTO «Объект», а что «Список») можно использовать следующий прием:

Функция КоллекцияXDTO(Элемент)

    Если ТипЗнч(Элемент)=Тип("ОбъектXDTO") Тогда
    
        МассивXDTO = Новый Массив;
        МассивXDTO.Добавить(Элемент);
        Возврат МассивXDTO;
        
    Иначе

        Возврат Элемент;
        
    КонецЕсли;
    
    
КонецФункции


// . . . далее в коде обход
Для Каждого Item из КоллекцияXDTO(ОбъектXDTO.Items) Цикл

    // . . . обработка

КонецЦикла;

WEB и HTTP сервисы

Пример получения курса валют с WS ЦБРФ

	ТекПользователь = "ВебСервис";
	Пароль = "";
	// Пользователю "ВебСервис" даны права "Использование" только на WEB-Сервис,
	// а в процедуре WEB-Сервиса устанавливается ПривелегированныйРежим
	
	МестоположениеWSDLфайла = "http://localhost/L/ws/SellData.1cws?wsdl";
	// Адрес публикации: ""http://localhost/L", имя файла публикации "SellData.1cws"
	
	ОпределениеWS = Новый WSОпределения(МестоположениеWSDLфайла, ТекПользователь, Пароль);
	
	URIПространстваИменСервиса = "http://wiki.katkov-a.ru/SellData";
	ИмяСервиса = "SellData";
	ИмяТочкиПодключения = "SellDataSoap";
	
	WSПрокси = Новый WSПрокси(ОпределениеWS, URIПространстваИменСервиса, ИмяСервиса, ИмяТочкиПодключения);
	WSПрокси.Пользователь = ТекПользователь;
	WSПрокси.Пароль = Пароль;
	// WSПрокси также может быть создан на основании WS-Ссылки
	
	Ответ = WSПрокси.GetData(Параметр);
	// GetData - Операция WEB-Сервиса
	
	Если ТипЗнч(Ответ) = Тип("ОбъектXDTO") Тогда
		XML = Новый ЗаписьXML;
		XML.УстановитьСтроку();
		WSПрокси.ФабрикаXDTO.ЗаписатьXML(XML, Ответ); 
		ТекстОтвета = XML.Закрыть();
	Иначе
		ТекстОтвета = Строка(Ответ);
	КонецЕсли;

Функция возвращает XDTO-объект, сформированный на основании документа «Реализация товаров и Услуг» по номеру документа.

Функция GetData(Номер)
	
	Если СокрЛП(Номер) = "" Тогда
		Возврат Неопределено;
	КонецЕсли; 
	
	УстановитьПривилегированныйРежим(Истина);
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	РеализацияТоваровТоварыИУслуги.Ссылка.Ссылка КАК Ссылка,
		|	РеализацияТоваровТоварыИУслуги.Ссылка.Номер КАК Номер,
		|	РеализацияТоваровТоварыИУслуги.Ссылка.Дата КАК Дата,
		|	РеализацияТоваровТоварыИУслуги.НомерСтроки,
		|	РеализацияТоваровТоварыИУслуги.Номенклатура КАК НоменклатураСсылка,
		|	РеализацияТоваровТоварыИУслуги.Количество,
		|	РеализацияТоваровТоварыИУслуги.Цена,
		|	РеализацияТоваровТоварыИУслуги.Сумма
		|ИЗ
		|	Документ.РеализацияТоваров.ТоварыИУслуги КАК РеализацияТоваровТоварыИУслуги
		|ГДЕ
		|	РеализацияТоваровТоварыИУслуги.Ссылка.Номер = &Номер
		|
		|УПОРЯДОЧИТЬ ПО
		|	РеализацияТоваровТоварыИУслуги.НомерСтроки
		|ИТОГИ
		|	МАКСИМУМ(Номер),
		|	МАКСИМУМ(Дата)
		|ПО
		|	Ссылка";
		
	Запрос.УстановитьПараметр("Номер", Номер);
	
	РезультатЗапроса = Запрос.Выполнить();
	Если РезультатЗапроса.Пустой() Тогда
		Возврат Неопределено;
	КонецЕсли; 
	
	ВыборкаДокумент = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
	
	ДокументТип = ФабрикаXDTO.Тип("http://wiki.katkov-a.ru/SellData", "ДокументРеализации");
	СтрокаТЧТип = ФабрикаXDTO.Тип("http://wiki.katkov-a.ru/SellData", "СтрокаТЧ_Товары");
	НоменклатураТип = ФабрикаXDTO.Тип("http://wiki.katkov-a.ru/SellData", "Номенклатура");
	
	Пока ВыборкаДокумент.Следующий() Цикл
		
		Документ = ФабрикаXDTO.Создать(ДокументТип);
		ЗаполнитьЗначенияСвойств(Документ, ВыборкаДокумент);
		
		ВыборкаДетальныеЗаписи = ВыборкаДокумент.Выбрать();
	
		Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
			
			СтрокаТЧ = ФабрикаXDTO.Создать(СтрокаТЧТип);
			
			Номенклатура = ФабрикаXDTO.Создать(НоменклатураТип);
			ЗаполнитьЗначенияСвойств(Номенклатура, ВыборкаДетальныеЗаписи.НоменклатураСсылка);
			СтрокаТЧ.Номенклатура = Номенклатура;
			
			ЗаполнитьЗначенияСвойств(СтрокаТЧ, ВыборкаДетальныеЗаписи);
						
			Документ.СтрокаТЧ_Товары.Добавить(СтрокаТЧ);
			
		КонецЦикла;
	КонецЦикла;
	
	УстановитьПривилегированныйРежим(Ложь);
	
	Возврат Документ;
	
КонецФункции

XSD-схема возвращаемого объекта:

<xs:schema xmlns:tns="http://wiki.katkov-a.ru/SellData" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://wiki.katkov-a.ru/SellData" attributeFormDefault="unqualified" elementFormDefault="qualified">
	<xs:complexType name="ДокументРеализации">
		<xs:sequence>
			<xs:element name="Номер" type="xs:string"/>
			<xs:element name="Дата" type="xs:dateTime"/>
			<xs:element name="СтрокаТЧ_Товары" type="tns:СтрокаТЧ_Товары" maxOccurs="unbounded"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="Номенклатура">
		<xs:sequence>
			<xs:element name="Код" type="xs:string"/>
			<xs:element name="Наименование" type="xs:string"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="СтрокаТЧ_Товары">
		<xs:sequence>
			<xs:element name="Номенклатура" type="tns:Номенклатура"/>
			<xs:element name="Количество" type="xs:float"/>
			<xs:element name="Цена" type="xs:float"/>
			<xs:element name="Сумма" type="xs:float"/>
		</xs:sequence>
	</xs:complexType>
</xs:schema>