Для работы с XML-представлениями значений простых типов предназначены два метода глобального контекста: XMLСтрока() и XMLЗначение().
Метод XMLСтрока() имеет единственный параметр – значение, для которого нужно получить XML-представление. Это значение должно относиться к типу, являющемуся простым с точки зрения XML-сериализации. В противном случае будет вызвано исключение. При нормальном завершении функция возвращает строку, которая может быть использована как текст элемента XML, представляющего значение простого типа.
Метод XMLЗначение() выполняет противоположную задачу. У этого метода два параметра. Первый параметр – тип значения, которое нужно получить из строки, второй параметр – сама строка.
Для преобразования типа данных «1С:Предприятия» в тип данных XML и наоборот предназначены методы XMLТип() и ИзXMLТипа(). Метод XMLТип() имеет один параметр – тип, для которого нужно получить соответствующий тип данных XML. Если соответствующий тип данных XML определен, то метод возвращает значение типа ТипДанныхXML. Если же соответствующего типа данных XML нет, то метод возвращает значение Неопределено.
Метод ИзXMLТипа() имеет два варианта вызова. В первом варианте метод имеет единственный параметр типа ТипДанныхXML. Во втором варианте параметра два: имя типа XML и пространство имен. В обоих случаях метод возвращает соответствующий типу данных XML тип данных «1С:Предприятия», если таковой имеется, или Неопределено в противном случае.
Поскольку большинство методов для работы с данными XML (за исключением примитивных типов данных) не работают на клиенте, а получать файл с данными пользователю нужно в основном именно на клиенте, здесь и далее мы будем использовать следующий подход. При записи данных XML будем производить необходимую обработку данных на сервере, записывать эти данные во временный файл, в виде двоичных данных сохранять файл во временном хранилище и адрес этих данных в хранилище передавать на клиент. И затем уже получать файл на клиенте по адресу во временном хранилище. При чтении данных XML будем сохранять XML-документ во временном хранилище и адрес данных в хранилище передавать в северную процедуру, в которой документ будет получаться из временного хранилища, записываться во временный файл, и будет производиться чтение документа.
Для записи простых типов данных XML можно использовать следующий фрагмент кода (листинг 6.61).
Листинг 6.61. Процедура «ЗаписьПростыхТиповДанных()»
&НаКлиенте
Процедура ЗаписьПростыхТиповДанных(Команда)
АдресДокументаВХранилище = ЗаписьПростыхДанныхXML();
НачатьПолучениеФайлаССервера(АдресДокументаВХранилище);
КонецПроцедуры
В обработчике команды для записи XML-документа вызывается серверная функция ЗаписьПростыхДанныхXML(), в которой производится необходимая обработка данных, затем эти данные записываются во временный файл, который в виде двоичных данных сохраняется во временном хранилище, и адрес этих данных в хранилище возвращается на клиент (листинг 6.62).
Листинг 6.62. Функция «ЗаписьПростыхДанныхXML()»
&НаСервереБезКонтекста
Функция ЗаписьПростыхДанныхXML()
ИмяФайлаXML = КаталогВременныхФайлов() + "temp.xml";
Файл = Новый ЗаписьXML;
Файл.ОткрытьФайл(ИмяФайлаXML);
Файл.ЗаписатьОбъявлениеXML();
Файл.ЗаписатьНачалоЭлемента("Корневой");
// Записать значение типа Число.
// Получить значение "ТипДанныхXML" для числа.
ТипXML = XMLТипЗнч(1000);
// Создать элемент, имя которого совпадает с именем типа XML,
// при этом записать и пространство имен типа XML.
Файл.ЗаписатьНачалоЭлемента(ТипXML.ИмяТипа, ТипXML.URIПространстваИмен);
Файл.ЗаписатьТекст(XMLСтрока(1000));
Файл.ЗаписатьКонецЭлемента();
// Записать значение типа Строка.
ТипXML = XMLТипЗнч("Иванов");
Файл.ЗаписатьНачалоЭлемента(ТипXML.ИмяТипа, ТипXML.URIПространстваИмен);
Файл.ЗаписатьТекст(XMLСтрока("Иванов"));
Файл.ЗаписатьКонецЭлемента();
// Записать значение типа Дата.
ТипXML = XMLТипЗнч('2020-01-31T12:00:00Z');
Файл.ЗаписатьНачалоЭлемента(ТипXML.ИмяТипа, ТипXML.URIПространстваИмен);
Файл.ЗаписатьТекст(XMLСтрока('2020-01-31T12:00:00Z'));
Файл.ЗаписатьКонецЭлемента();
// Записать значение типа Булево.
ТипXML = XMLТипЗнч(true);
Файл.ЗаписатьНачалоЭлемента(ТипXML.ИмяТипа, ТипXML.URIПространстваИмен);
Файл.ЗаписатьТекст(XMLСтрока(true));
Файл.ЗаписатьКонецЭлемента();
// Получить ссылку на элемент номенклатуры
СсылкаНаНоменклатуру = Справочники.Товары.НайтиПоКоду("000000003");
ТипXML = XMLТипЗнч(СсылкаНаНоменклатуру);
Файл.ЗаписатьНачалоЭлемента(ТипXML.ИмяТипа, ТипXML.URIПространстваИмен);
Файл.ЗаписатьТекст(XMLСтрока(СсылкаНаНоменклатуру));
Файл.ЗаписатьКонецЭлемента();
Файл.ЗаписатьНачалоЭлемента(ТипXML.ИмяТипа, ТипXML.URIПространстваИмен);
Файл.ЗаписатьТекст(Строка(СсылкаНаНоменклатуру));
Файл.ЗаписатьКонецЭлемента();
Файл.ЗаписатьКонецЭлемента();
Файл.Закрыть();
Возврат ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяФайлаXML));
КонецФункции
Особенность вышеприведенного механизма заключается в том, что при записи элемента в его имя записывается имя типа XML (получаемого при обращении к значению, возвращенному методом XMLТипЗнч()). Также записывается пространство имени типа. Следует отметить, что тип XML можно было получить и при обращении к методу XMLТип().
Затем в процедуре, инициировавшей запись данных XML на клиенте, с помощью метода глобального контекста НачатьПолучениеФайлаССервера() начинается получение файла по адресу во временном хранилище, и файл сохраняется в локальную файловую систему пользователя. При этом пользователю предлагается диалог для выбора месторасположения получаемого файла.
В результате выполнения фрагмента кода сформируется следующий документ (листинг 6.63).
Листинг 6.63. Пример сформированного XML-документа
<?xml version="1.0" encoding="UTF-8"?>
<Корневой>
<d2p1:decimal xmlns:d2p1="http://www.w3.org/2001/XMLSchema">1000</d2p1:decimal>
<d2p1:string xmlns:d2p1="http://www.w3.org/2001/XMLSchema">Иванов</d2p1:string>
<d2p1:dateTime xmlns:d2p1="http://www.w3.org/2001/XMLSchema">2020-01-31T12:00:00</d2p1:dateTime>
<d2p1:boolean xmlns:d2p1="http://www.w3.org/2001/XMLSchema">true</d2p1:boolean>
<CatalogRef.Товары>34c5d799-7636-11e9-88b7-642737df2048</CatalogRef.Товары>
<CatalogRef.Товары>Кофемашина</CatalogRef.Товары>
</Корневой>
Обратите внимание на следующий факт. Пространство имен типов должно быть записано для каждого элемента с данными. Однако в пятом и шестом элементах (для ссылки справочника Товары) оно не определено. Так и должно быть, ведь для типов данных, производных от объектов конфигурации, пространство имен не определяется.
Кроме того, обратите внимание на различие результата записи ссылки. В первом случае используется метод XMLСтрока(), записывается значение уникального идентификатора ссылки. Во втором записывается представление ссылки (чаще всего это наименование).
Для чтения выгруженного XML-документа (см. листинг 6.63) может использоваться следующий программный код (листинг 6.64).
Листинг 6.64. Пример чтения XML-документа
&НаКлиенте
Процедура ЧтениеПростыхТиповДанных(Команда)
АдресВременногоХранилища = "";
ОповещениеОЗавершении = Новый ОписаниеОповещения("ЧтениеПростыхТиповДанныхЗавершение", ЭтотОбъект);
НачатьПомещениеФайлаНаСервер(ОповещениеОЗавершении, , , АдресВременногоХранилища, , УникальныйИдентификатор);
КонецПроцедуры
В обработчике команды для чтения XML-документа с помощью метода глобального контекста НачатьПомещениеФайлаНаСервер() начинается помещение файла с данными XML из локальной файловой системы во временное хранилище. При этом пользователю предлагается диалог для выбора помещаемого файла.
В метод НачатьПомещениеФайлаНаСервер() первым параметром передается описание оповещения, указывающее на экспортную процедуру ЧтениеПростыхТиповДанныхЗавершение(), которая будет выполнена, после того как файл с данными XML будет помещен во временное хранилище (листинг 6.65).
Листинг 6.65. Процедура «ЧтениеПростыхТиповДанныхЗавершение()»
&НаКлиенте
Процедура ЧтениеПростыхТиповДанныхЗавершение(ОписаниеПомещенногоФайла, Дополнительно) Экспорт
ЧтениеПростыхДанныхXML(ОписаниеПомещенногоФайла.Адрес);
КонецПроцедуры
После того как файл будет помещен, адрес данных в хранилище (ОписаниеПомещенногоФайла.Адрес) передается в серверную процедуру ЧтениеПростыхДанныхXML(), в которой документ по этому адресу получается из временного хранилища, записывается во временный файл, и производится чтение документа (листинг 6.66).
Листинг 6.66. Процедура «ЧтениеПростыхДанныхXML()»
&НаСервереБезКонтекста
Процедура ЧтениеПростыхДанныхXML(АдресДокументаВХранилище)
Сообщение = Новый СообщениеПользователю();
ДанныеДокумента = ПолучитьИзВременногоХранилища(АдресДокументаВХранилище);
ИмяФайлаXML = КаталогВременныхФайлов() + "temp.xml";
ДанныеДокумента.Записать(ИмяФайлаXML);
Файл = Новый ЧтениеXML;
Файл.ОткрытьФайл(ИмяФайлаXML);
// Спозиционироваться на начале элемента "Корневой".
Файл.Прочитать();
// Начало элемента "decimal".
Файл.Прочитать();
// Получить тип «1С:Предприятия» из имени элемента (совпадающего с именем типа) и URI пространства имен.
ТипЗначения = ИзXMLТипа(Файл.ЛокальноеИмя, Файл.URIПространстваИмен);
// Спозиционироваться на тексте.
Файл.Прочитать();
ПолученноеЗначение = XMLЗначение(ТипЗначения, Файл.Значение);
Сообщение.Текст = Строка(ПолученноеЗначение);
Сообщение.Сообщить();
// Конец элемента "decimal".
Файл.Прочитать();
// Начало элемента "string".
Файл.Прочитать();
ТипЗначения = ИзXMLТипа(Файл.ЛокальноеИмя, Файл.URIПространстваИмен);
Файл.Прочитать();
ПолученноеЗначение = XMLЗначение(ТипЗначения, Файл.Значение);
Сообщение.Текст = Строка(ПолученноеЗначение);
Сообщение.Сообщить();
// Конец элемента "string".
Файл.Прочитать();
// Начало элемента "dateTime".
Файл.Прочитать();
ТипЗначения = ИзXMLТипа(Файл.ЛокальноеИмя, Файл.URIПространстваИмен);
Файл.Прочитать();
ПолученноеЗначение = XMLЗначение(ТипЗначения, Файл.Значение);
Сообщение.Текст = Строка(ПолученноеЗначение);
Сообщение.Сообщить();
// Конец элемента "dateTime".
Файл.Прочитать();
// Начало элемента "boolean".
Файл.Прочитать();
ТипЗначения = ИзXMLТипа(Файл.ЛокальноеИмя, Файл.URIПространстваИмен);
Файл.Прочитать();
ПолученноеЗначение = XMLЗначение(ТипЗначения, Файл.Значение);
Сообщение.Текст = Строка(ПолученноеЗначение);
Сообщение.Сообщить();
// Конец элемента "boolean".
Файл.Прочитать();
// Начало элемента "CatalogRef.Товары".
Файл.Прочитать();
// Получить тип «1С:Предприятия» из имени элемента (совпадающего с именем типа) и URI пространства имен.
ТипЗначения = ИзXMLТипа(Файл.ЛокальноеИмя, Файл.URIПространстваИмен);
Файл.Прочитать();
ПолученноеЗначение = XMLЗначение(ТипЗначения, Файл.Значение);
Сообщение.Текст = Строка(ПолученноеЗначение);
Сообщение.Сообщить();
// Конец элемента "CatalogRef.Товары".
Файл.Прочитать();
// Начало элемента "CatalogRef.Товары".
Файл.Прочитать();
Файл.Прочитать();
ПолученноеЗначение = XMLЗначение(Тип("Строка"), Файл.Значение);
Сообщение.Текст = Строка(ПолученноеЗначение);
Сообщение.Сообщить();
// Конец элемента "CatalogRef.Товары"
Файл.Прочитать();
Файл.Закрыть();
КонецПроцедуры