gifts2017

Преобразование XML в объекты 1С

Опубликовал Вадим Миляев (PrinzOfMunchen) в раздел Обмен - Обмен через XML

Преобразование XML в типовые объекты 1С всего лишь парой строк кода.

В современном мире веб-технологий для получения какой-либо информации повсеместно используются различные web и http сервисы, обменивающиеся данными, записанными в определенных, заранее согласованных форматах по определенным правилам. Одним из самых популярных таких форматов является XML. Естественно, приходится с ним работать и из 1С...

 

Что чаще всего приходится делать с XML в 1С?

1. Получить XML (Из уже существующего файла, через веб-сервис, http-сервис и т.д.);

2. Каким-то образом вытянуть нужные нам данные из полученных данных.

 

Хотелось бы остановиться на втором пункте. Какие методы используете для этого вы? Я встречал, в основном, несколько вариантов: XDTO и ЧтениеXML.  XDTO классная штука, которая позволяет быстро из xml-ки получить заранее определенные объекты по заданным нами правилами. Удобно. Но нужно описывать и создавать XDTO-пакеты, изменять конфигурацию....Второй вариант, через объект ЧтениеXML. Он наиболее прост и популярен. Создали его, показали ему файлик, и с помощью метода "Прочитать()" обходим в цикле. Все работает, но, это все таки цикл, а файл может быть большим. Да и что бы в этом цикле получить только нужную информацию приходится делать кучу условий...

Так что же делать? А может, можно обойтись без циклов, условий, познаний в XDTO? Можно.

Итак, расскажу, какой способ использую я. Практически всегда мы можем получить данные о схеме получаемых XML-данных. Ну или хотя бы примерно мы должны знать, где там и что лежит. Поэтому, с помощью объекта "ПреобразованиеXSL" мы можем преобразовать данные к нужной схеме. И вот тут мы можем схитрить.

Я думаю, практически все слышали о паре методов "ЗначениеВСтрокуВнутр" и "ЗначениеИзСтрокиВнутр". Как связано с нашим вопросом? А вот как. Типовые объекты, будь то, например, структура или таблица значений, с помощью этих методов можно преобразовать в строку и обратно.  Причем, для объектов одного типа правила получения этой строки одни и те же. А что нам мешает, с помощью XSL из XML получить данные в таком же формате, а потом с помощью метода "ЗначениеИзСтрокиВнутр" получить уже готовый, заполненный, объект 1С? Ничего. Причем, делать мы будем преобразование ТЕКСТА, а значит, отработает оно очень быстро.

Приведу пример (обработка с примеров для УФ 8.3 во вложении). Возьмем для примера такую xml.

 

 Здесь содежатся данные о заказе, адресе покупателя и выбранных товарах. На выходе нам нужно получить таблицу, вида:

 Номер заказа   Адрес   Номенклатура    Количество   Сумма 

 

Для этого, для платформ 8.3, воспользуемся следующей строкой преобразования:

 

 В результате преобразования получаем:

{"#",acf6192e-81ca-46ef-93a6-5a6968b78663,

{9,
{5,
{0,"НомерЗаказа",
{"Pattern"},"Строка",0},
{1,"Адрес",
{"Pattern"},"Строка",0},
{2,"Номенклатура",
{"Pattern"},"Строка",0},
{3,"Количество",
{"Pattern",
{"N",10,2,0}
},"",0},
{4,"Сумма",
{"Pattern",
{"N",15,4,0}
},"",0}
},
{2,5,0,0,1,1,2,2,3,3,4,4,
{1,2,{2,0,5,{"S","99503"},{"S","Tai Yee"},{"S","Lawnmower"},{"N",1},{"N",148.95},0},
{2,1,5,{"S","99503"},{"S","Tai Yee"},{"S","Baby Monitor"},{"N",2},{"N",39.98},0}},
4,1},{0,0}}}


В коде все преобразование выглядит так:

ПреобразованиеXSL = Новый ПреобразованиеXSL;
ПреобразованиеXSL.ЗагрузитьИзСтроки(Объект.СтрокаПреобразования);
Объект.СтрокаИтоговая = ПреобразованиеXSL.ПреобразоватьИзСтроки(Объект.СтрокаXML);

После этого к получившейся строке применяем метод "ЗначенийИзСтрокиВнутр" и получаем:

 

Все преобразование происходит практически мгновенно. Во вложении прикрепил обработку для тестирования описанного механизма с возможностью использования примера из статьи.

 

P.S. Не уверен, что никто ранее такого ни делал, но я ранее об этом методе не слышал.

P.S.S. То, как должна выглядеть сериализованная таблица значений, вычислял эксперементально, если у кого-то есть ссылка на какую-то информацию, буду благодарен. И да, для 8.2 и 8.3 есть небольшие отличия. Если будет нужна строка преобразования для 8.2, пишите в комментах.

UPD. Добавлена обработка для обычных форм с примером для 8.2.

Скачать файлы

Наименование Файл Версия Размер
Тест преобразований (Управляемые формы, 8.3) 47
.epf 8,40Kb
20.10.15
47
.epf 8,40Kb Скачать
Тест преобразований (Обычные формы, 8.2) 16
.epf 8,17Kb
20.10.15
16
.epf 8,17Kb Скачать

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Дмитрий Шерстобитов (DitriX) 18.10.15 08:34
Плохо искали. Ищите по термину сериализация.
2. Andrey (kentavr27) 18.10.15 14:35
Да, метод иногда полезный. Сам ним пользуюсь для передачи данных через web-сервисы между базами. На это есть по-крайней мере 2 веские причины:
1. После преобразования ЗначениеВСтрокуВнутр() занимает гораздо меньший объем, чем обычный XML
2. Не нужно строить никаких схем. На одном конце загнал в строку, на другом получил из строки уже готовый объект (при сходной, но не абсолютно одинаковой, структуре данных). И это, действительно всего парой строк кода!
Одно огорчает, что данный метод не доступен в мобильных приложениях. XML -- это может быть и хорошо, но слишком уж много места занимает. При обмене большими объемами данных выжирает много трафика. А как запихнуть некий подобный механизм (с минимальным размером данных) в мобильное приложение -- пока не знаю.
Ну и к тому же еще настораживает оговорка СП: Используется для сохранения функциональной совместимости с 1С:Предприятием 7.7. Использовать для других целей не рекомендуется. В связи с чем? -Загадка.
3. Вадим Миляев (PrinzOfMunchen) 18.10.15 14:40
(1) DitriX, спасибо за информацию, обязательно поищу.
P.S. Пользуясь случаем, огромное вам спасибо за ваши статьи и уроки по мобильной платформе. Они шикарны.).
4. Вадим Миляев (PrinzOfMunchen) 18.10.15 14:49
(2) kentavr27, тут основная фишка не в использовании связки "ЗначениеИзСтрокиВнутр" <-> "ЗначениеВСтрокуВнутр" а именно XLS преобразование не наших xml-фалов в объекты 1С. Удобно и быстро. Вообще, пришлось воспользоваться когда нужно было загружать данные от http-сервиса, возвращающего xml-ку с большим объемом данных, где полезных для меня было минимум. Через ЧтениеXML было лениво загружать, писать кучу условий....вот и "придумал". )))
5. Евгений Стоянов (quick) 18.10.15 22:48
Хорошее решение для простых случаев.
Я написал одно время модуль для таблиц и списков на python
https://gist.github.com/WorldException/de7199f8dc9659656336
Позволяет делать так
v=V8Table(['test1','test2','test3'])
v.add(['000','000','000"test"'])
print v.export().encode('cp1251')
...Показать Скрыть


А так же для 7-ки
https://gist.github.com/WorldException/cdfce52e9da29437d724
Или совсем прямой доступ sql к базе через парсинг конфигурации
https://github.com/WorldException/v7py
DoctorRoza; +1 Ответить
6. Dmitry Bas (b-dm) 19.10.15 10:24
Было бы здорово иметь такую обработку и для обычных форм!
7. Вадим Миляев (PrinzOfMunchen) 19.10.15 10:58
(6) b-dm, есть и для обычных форм вариант. Вечером доберусь до домашнего компьютера и добавлю в публикацию.
8. Maxim Kolkin (the1) 20.10.15 08:56
Как по мне, так XSL штука еще более богомерзкая, чем XML. Сталкивался с ней лет 10 назад, когда еще 1С не занимался.
П.С. Но за идею плюсую.
9. Вадим Миляев (PrinzOfMunchen) 20.10.15 11:39
(6) b-dm, выложил обработку для обычных форм со строкой преобразования для 8.2.
10. Антон Антонов (monkbest) 21.10.15 08:57
Я помню в семерке методы "ЗначениеВСтрокуВнутр" и "ЗначениеИзСтрокиВнутр" жрали очень много оперативной памяти и падали с нехваткой памяти на боле менее больших данных. Я на их основе делал распределенку в 7.7, (в стандартном РИБе нельзя было фильтровать данные), совал элемент БД в список значений (структур в 7.7 не было), списки значений пихал в общий список значений и это чудо в "ЗначениеВСтрокуВнутр", получалось очень круто и на халяву, никакой зависимости от структуры БД. Но когда применил этот метод на более менее больших базах, сразу уперся в нехватку памяти. примерно пропорции, если правильно помню, были такие, если выходной текстовик 10Mb то оперативы сжиралось в момент преобразования почти 1Gb.
Но это в момент преобразования в строку, при обратном все происходило мгновенно и без лишних затыков
11. Владислав Мороз (vlad.frost) 21.10.15 09:32
Выдержка из Синтакс-помощника для методов ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр:
Используется для сохранения функциональной совместимости с 1С:Предприятием 7.7. Использовать для других целей не рекомендуется.
12. Яков Коган (Yashazz) 21.10.15 19:04
Забавный способ. За идею плюсую.
13. Алексей Сидоров (AlexiyI) 26.10.15 18:28
А обратно в исходный XML преобразовать можно?
По поводу шаблонов преобразования: можно тестить онлайн, например тут
14. Вадим Миляев (PrinzOfMunchen) 26.10.15 18:46
(13) AlexiyI, можно, но зачем? Если нужно объект преобразовать в xml, есть типовая сериализация.
Да таких сайтов полно. Во вложенных обработках можно сразу увидеть результат в виде таблицы значений, кроме того же самого функционала по онлайн-преобразованию.
15. Алексей Сидоров (AlexiyI) 27.10.15 11:12
(14) PrinzOfMunchen, если мы можем XML быстро преобразовать по шаблону в строку, а затем в таблицу, то думаю, было бы полезно так же преобразовать таблицу в строку и обратно в XML. Но похоже, метода обратного преобразования у ПреобразованиеXSL нет.
16. Вадим Миляев (PrinzOfMunchen) 27.10.15 13:32
(15) AlexiyI,
преобразовать таблицу в строку
?
Зачем нам этот лишний этап? Можно сразу из таблицы получить XML:
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
НоваяЗаписьXML = Новый ЗаписьXML();
НоваяЗаписьXML.ОткрытьФайл(ИмяВременногоФайла);
ТаблицаЗначений = Новый ТаблицаЗначений;
ТаблицаЗначений.Колонки.Добавить("ИмяКолонки");
НоваяСтрока = ТаблицаЗначений.Добавить();
НоваяСтрока.ИмяКолонки = "Пример содержания колонки";
СериализаторXDTO.ЗаписатьXML(НоваяЗаписьXML, ТаблицаЗначений, НазначениеТипаXML.Явное);
...Показать Скрыть


И все. На выходе XML. А уж его, если сильно хочется, преобразуйте как душе угодно.
17. Алексей Сидоров (AlexiyI) 04.11.15 15:49
По вдохновению PrinzOfMunchen решил написать универсальное преобразование xml в строку, но не в виде таблицы, а используя типы: массив, структура, строка.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
  <!--КОРЕНЬ-->
  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>
  <!--МАССИВЫ-->
  <xsl:template match="customers">
    <xsl:call-template name="array"/>
  </xsl:template>
  <!--СТРУКТУРЫ-->
  <xsl:template match="customer|phone">
    <xsl:call-template name="structure"/>
  </xsl:template>
  <!--ЭЛЕМЕНТЫ СТРУКТУРЫ - МАССИВЫ-->
  <xsl:template match="phones">
    <xsl:call-template name="struct_elem">
      <xsl:with-param name="type_name" select="'array'"/>
    </xsl:call-template>
  </xsl:template>
  <!--ЭЛЕМЕНТЫ СТРУКТУРЫ - СТРОКИ-->
  <xsl:template match="code|number|name|address|state">
    <xsl:call-template name="struct_elem" mode="str">
      <xsl:with-param name="type_name" select="'string'"/>
    </xsl:call-template>
  </xsl:template>
  <!--////////////////////////////////////////////////-->
  <!--3. ОПРЕДЕЛЕНИЕ СТРОКИ-->
  <xsl:template name="string">
  {"S","<xsl:value-of select="self::*"/>"}
  </xsl:template>
  <!--////////////////////////////////////////////////-->
  <!--1. ОПРЕДЕЛЕНИЕ МАССИВА-->
  <xsl:template name="array">{"#",51e7a0d2-530b-11d4-b98a-008048da3034,
    {<xsl:value-of select="count(*)"/>
    <xsl:if test="count(*) != 0">,</xsl:if>
    <xsl:apply-templates select="*"/>}}
  </xsl:template>
  <!--////////////////////////////////////////////////-->
  <!--2. ОПРЕДЕЛЕНИЕ СТРУКТУРЫ-->
  <xsl:template name="structure">{"#",4238019d-7e49-4fc9-91db-b6b951d5cf8e,
    {<xsl:value-of select="count(*)"/>
    <xsl:if test="count(*) != 0">,</xsl:if>
    <xsl:apply-templates select="*"/>}}
    <xsl:if test="count(following-sibling::*) != 0">,</xsl:if>
  </xsl:template>
  <!--////////////////////////////////////////////////-->
  <!--2. ОПРЕДЕЛЕНИЕ ЭЛЕМЕНТА СТРУКТУРЫ-->
  <xsl:template name="struct_elem">
    <xsl:param name="type_name" select="'NULL_PARAM'"/>
    <!--Ключ-->
    {{"S","<xsl:value-of select="name()"/>"},
    <!--Значение-->
    <xsl:choose>
      <xsl:when test="$type_name = 'string'">
        <xsl:call-template name="string"/>
      </xsl:when>
      <xsl:when test="$type_name = 'array'">
        <xsl:call-template name="array"/>
      </xsl:when>
      <xsl:when test="$type_name = 'structure'">
        <xsl:call-template name="structure"/>
      </xsl:when>
    </xsl:choose>}
    <xsl:if test="count(following-sibling::*) != 0">,</xsl:if>
  </xsl:template>
</xsl:stylesheet>
...Показать Скрыть

Файл xml использовал следующий:
<?xml version="1.0"?>
<customers>
   <customer>
      <name>John Smith</name>
      <address>123 Oak St.</address>
      <state>WA</state>
      <phones>
         <phone>
		[1C-CODE](111)
...Показать Скрыть

<number>123-4567</number>
</phone>
<phone>
(222)

<number>321-4567</number>
</phone>
</phones>
</customer>
...
</customers>[/1C-CODE]
Здесь элемент xml-документа может выступать в качестве одной из сущностей:
1. Массив (корень customers).
2. Структура, выступающая в качестве элемент массива (customer как элемент массива customers).
3. Элемент структуры с типом "строка".
4. Элемент структуры с типом "массив". По аналогии можно еще добавить элемент структуры с типом "структура", если понадобится.
Получилось довольно универсально для первого моего раза: для применения данного шаблона к другому XML-файлу достаточно указать нужные паттерны в атрибутах match элементов template.
Из недостатков:
1. Так и не получилось избавиться от блока <xsl:choose> (смотрится не очень красиво). Не смог передать параметр $type_name в атрибут name элемента <xsl:call-template>, как ни крутил. Если кто знает как - напишите.
2. Не применимо (если не доработать) для XML-документов с нефиксированной структурой, т.е. если в одном из элементов <customer> появится <surname>, то его нужно также прописать в template. Либо какие-то элементы, например тот же <surname>, обрабатывать не нужно, то помимо параметра $type_name необходимо добавить параметр $path, чтобы вместо выражения типа count(*) использовать count($path). Изначально так и делал, но в итоге захотел сделать шаблон более "худым" и убрал параметр.
3. Возможно добавить другие простые типы: число, дата. Но думаю, в данном случае можно эти значения преобразовать из строки.
Прикрепленные файлы:
XMLFile.xml
Transform.xsl
PrinzOfMunchen; +1 Ответить 1
18. Дмитрий Тарасов (tarassov) 04.11.15 17:43
Я ранее поднимал эту же тему на форуме, в том числе показал, как получать из XML с помощью XSL-преобразования XDTO соответствующий таблиые значений.
Пожалуйста посмотрите Читаем XML, хочется получить ТаблицаЗначений через XDTO и сравните

19. Алексей Сидоров (AlexiyI) 04.11.15 20:45
(18) tarassov, именно так я и хотел сделать сначала :), но не знаю правил преобразования Сериализатора XDTO. А со ЗначениеВСтрокуВнутр() понять логику преобразования методом проб и ошибок проще, и можно обойтись без документации.
Знал бы к чему преобразовывать, пошел бы и я этим путем, но преобразовывать в таблицу, думаю, не совсем по феншую, т.к. структура XML может быть очень разнообразной, с глубокой вложенностью - в таблице без дублирования данных не обойтись. Я так понимаю, тема с сериализатором XDTO до конца не раскрыта? По ссылке кидает непонятно куда так что оставлю здесь.
20. Алексей Сидоров (AlexiyI) 04.11.15 20:58
Ах да, я сравнил... Мой шаблон преобразует любую XML с любой вложенностью, а не только "плоскую" и с одними атрибутами. Ну, не совсем любую: если тег <phones> будет в одном месте массивом, в другом структурой, в третьем строкой, то не сработает. Мой метод лучше :), ничего личного, просто бизнес :).
21. Алексей Сидоров (AlexiyI) 04.11.15 23:19
Переделал на вариант с сериализатором XDTO.
Шаблон такой:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
  <!--КОРЕНЬ-->
  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>
  <!--МАССИВЫ-->
  <xsl:template match="customers">
    <xsl:call-template name="value">
      <xsl:with-param name="type_name" select="'Array'"/>
      <xsl:with-param name="first_elem" select="'true'"/>
    </xsl:call-template>
  </xsl:template>
  <!--СТРУКТУРЫ-->
  <xsl:template match="customer|phone">
    <xsl:call-template name="value">
      <xsl:with-param name="type_name" select="'Structure'"/>
    </xsl:call-template>
  </xsl:template>
  <!--ЭЛЕМЕНТЫ СТРУКТУРЫ - МАССИВЫ-->
  <xsl:template match="phones">
    <xsl:call-template name="struct_elem">
      <xsl:with-param name="type_name" select="'Array'"/>
    </xsl:call-template>
  </xsl:template>
  <!--ЭЛЕМЕНТЫ СТРУКТУРЫ - СТРОКИ-->
  <xsl:template match="code|number|name|address|state">
    <xsl:call-template name="struct_elem">
      <xsl:with-param name="type_name" select="'xs:string'"/>
    </xsl:call-template>
  </xsl:template>
  <!--ЭЛЕМЕНТЫ СТРУКТУРЫ - СТРУКТУРЫ-->
  <xsl:template match="no_pattern">
    <xsl:call-template name="struct_elem">
      <xsl:with-param name="type_name" select="'Structure'"/>
    </xsl:call-template>
  </xsl:template>
  <!--////////////////////////////////////////////////-->
  <!--2. ОПРЕДЕЛЕНИЕ ЭЛЕМЕНТА СТРУКТУРЫ-->
  <xsl:template name="struct_elem">
    <xsl:param name="type_name" select="'NULL_PARAM'"/>
    <!--Ключ-->
    <xsl:text><Property name="</xsl:text>
    <xsl:value-of select="name()"/>
    <xsl:text>"></xsl:text>
    <!--Значение-->
    <xsl:call-template name="value">
      <xsl:with-param name="type_name" select="$type_name"/>
    </xsl:call-template>
    <xsl:text></Property></xsl:text>
  </xsl:template>
  <!--////////////////////////////////////////////////-->
  <!--2. ОПРЕДЕЛЕНИЕ ЗНАЧЕНИЯ ТИПА-->
  <xsl:template name="value">
    <xsl:param name="type_name" select="'NULL_PARAM'"/>
    <xsl:param name="first_elem" select="'false'"/>
    <xsl:text><Value </xsl:text>
    <xsl:if test="$first_elem = 'true'">
      <xsl:text>xmlns="http://v8.1c.ru/8.1/data/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" </xsl:text>
    </xsl:if>
    <xsl:text> xsi:type="</xsl:text>
    <xsl:value-of select="$type_name"/>
    <xsl:text>"></xsl:text>
    <xsl:choose>
      <xsl:when test="$type_name = 'xs:string'">
        <xsl:value-of select="self::*"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="*"/>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text></Value></xsl:text>
  </xsl:template>
</xsl:stylesheet>
...Показать Скрыть

Код такой:
ПреобразованиеXSL	= Новый ПреобразованиеXSL;
	Сериализатор		= Новый СериализаторXDTO(ФабрикаXDTO);
	ЧтениеXML			= Новый ЧтениеXML;
	
	ПреобразованиеXSL.ЗагрузитьИзСтроки(фТекстШаблонаXSL);
	СтрокаXML	= ПреобразованиеXSL.ПреобразоватьИзСтроки(фТекстXml);
	СтрокаXML	= СтрЗаменить(СтрокаXML, "<", "<");
	СтрокаXML	= СтрЗаменить(СтрокаXML, ">", ">");
	
	ЧтениеXML.УстановитьСтроку(СтрокаXML);
	Значение	= Сериализатор.ПрочитатьXML(ЧтениеXML);
	
	ЧтениеXML.Закрыть();
...Показать Скрыть

Правда, после xsl преобразования все символы "больше" и "меньше" заменились на ">" и "<", пришлось избавляться от них вручную, пробовал и CDATA и <text>. Возможно, достаточно в шаблон добавить какой-нибудь атрибут, чтобы само заработало. Если кто знает - напишите.
Спасибо, tarassov, что натолкнул на мысль. И код стал "худее"
22. Алексей Сидоров (AlexiyI) 04.11.15 23:24
Код не такой в стрзаменить() :) . При отправке комментария символы "больше" и "меньше" заменились на обратные.
Т.е. в стрзаменить меняем "[амперсант]lt;" на "<", а "[амперсант]gt;" на ">".
23. Вадим Миляев (PrinzOfMunchen) 05.11.15 03:29
(17) AlexiyI, Сильно не тестил, но работа видимо немаленькая проделана. )) Соберите эти правила для преобразования по типовым объектам, какой символ в строковом представлении объекта за что отвечает. Только учитывайте, что на разных платформах, немного по разному выглядят сериализованные строки. Было бы интересено взглянуть на такое. Мини-документация. )
24. Алексей Сидоров (AlexiyI) 05.11.15 09:29
(23) PrinzOfMunchen, я использую всего 3 типа: массив, структура и строка. Структура xml для сериализатора XDTO оказалась проще, чем структура строки внутр.
1. Строковое значение: <Value xsi:type="xs:string">строка значения</Value>.
2. Структура: <Value xsi:type="Structure"> элементы структуры</Value>.
3. Элемент структуры: <Property name="ИмяКлюча"> <Value xsi:type="любой_тип">значение элемента структуры</Value> </Property>.
4. Массив: <Value xsi:type="Array"> элементы массива </Value>. Элементы массива выглядят так: <Value/><Value/><Value/><Value/>... Значения <Value/> могут описываться как написано в п. 1, 2, 4, т.е. строка, структура и массив могут выступать в качестве элементов массива.

Пара нюансов:
1. В выложенном мной тексте шаблона символы "[амперсант]lt;" и "[амперсант]gt;" автоматически заменились на "<" и ">". Т.е. перед применением данного шаблона в тегах <xsl:text> нужно заменить "<" и ">" на "[амперсант]lt;" и "[амперсант]gt;".
2. Я совсем забыл про возможные атрибуты тегов xml. Думаю, некоторой доработкой шаблона можно каждое значение тега дополнять структурой с предопределенным именем, например "tag_attributes", и заполнять его всеми атрибутами.
25. Вадим Миляев (PrinzOfMunchen) 05.11.15 10:56
(24) AlexiyI,
Структура xml для сериализатора XDTO

Интересно. Надо будет посмотреть.
Будет время, попробую заняться.
26. Константин Юрин (kostyaomsk) 07.11.15 10:17
Полезный материал. Надо внимательно все просмотреть и проверить в конфигураторе.
27. Вячеслав Павелко (slawanix) 19.02.16 00:40
Автор, поделись пожалуйста источником, прочитав который я смогу расшифровать твою строку преобразования, и нарисовать свою строку под свою задачу. Если не трудно) И ведь есть еще некий XPath, он ведь тоже решает аналогичные задачи, да?
28. Вадим Миляев (PrinzOfMunchen) 02.03.16 13:19
(27) slawanix, смотрел курсы по XML и XSLT. Думаю полно таких в интернете. )