Замена ссылок на GUID-ы в таблице значений через XML


Практическое применение объекта 1С ПреобразованиеXSL — использование правила XSL для конвертации ссылочных типов в строку.

Warning

Данная статья не претендует на оригинальность и не является конечным решением.

Подходы решения задач и примеры программного кода несут исключительно обучающий характер.

 

Шаблон задачи области применения: есть произвольная таблица значений, к примеру, выгрузка результата запроса, которую необходимо передать в другую систему через COM, веб сервис или что-то еще . Для чтения таблицы значений без ошибок обращения к ссылкам необходимо преобразовать ссылки в GUID-ы.

Алгоритм преобразования:

  1. Таблица значений в xml:
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку("UTF-8");
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ТаблицаДанных);
    СтрокаXML = ЗаписьXML.Закрыть();

     

  2. Преобразователь XSL:
    ПреобразованиеXSL = Новый ПреобразованиеXSL;
    ПреобразованиеXSL.ЗагрузитьИзСтроки(СтрокаПравило);
    СтрокаРезультат = ПреобразованиеXSL.ПреобразоватьИзСтроки(СтрокаXML);
  3. Новая строка xml в таблицу значений:

    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(СтрокаРезультат);
    ТаблицаДанных = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
    ЧтениеXML.Закрыть();

     

Пример запроса одной ссылки:

ВЫБРАТЬ ПЕРВЫЕ 1
ИдентификаторыОбъектовМетаданных.Ссылка КАК Ссылка
ИЗ
Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных

Пример xml, созданный через СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ТаблицаДанных):

<?xml version="1.0" encoding="UTF-8"?>
<ValueTable 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">
<column>
<Name xsi:type="xs:string">Ссылка</Name>
<ValueType>
<Type>Null</Type>
<Type xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.ИдентификаторыОбъектовМетаданных</Type>
</ValueType>
<Title>Ссылка</Title>
<Width xsi:type="xs:decimal">25</Width>
</column>
<row>
<Value xmlns:d3p1="http://v8.1c.ru/8.1/data/enterprise/current-config" xsi:type="d3p1:CatalogRef.ИдентификаторыОбъектовМетаданных">627a6fb8-872a-11e3-bb87-005056c00008</Value>
</row>
</ValueTable>

Нужный результат:

<?xml version="1.0" encoding="utf-8"?>
<ValueTable 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">
<column>
<Name xsi:type="xs:string">Ссылка</Name>
<ValueType>
<Type>Null</Type>
<Type xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.ИдентификаторыОбъектовМетаданных</Type>
<Type>xs:string</Type></ValueType>
<Title>Ссылка</Title>
<Width xsi:type="xs:decimal">25</Width>
</column>
<row>
<Value xmlns:d3p1="http://v8.1c.ru/8.1/data/enterprise/current-config" xsi:type="xs:string">627a6fb8-872a-11e3-bb87-005056c00008</Value>
</row>
</ValueTable>

Правило трансформации XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:ones="http://v8.1c.ru/8.1/data/core"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<!-- установим способ вывода результата -->
<xsl:output method="xml" encoding="utf-8"/>

<!-- скопируем все узлы документа -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<!-- добавим тип строка во все колонки -->
<xsl:template match="ones:column/ones:ValueType">
<xsl:copy>
<xsl:apply-templates/>
<xsl:if test="not(ones:Type[contains(node(), 'xs:string')])">
<xsl:element namespace="http://v8.1c.ru/8.1/data/core" name="Type"
>xs:string</xsl:element>
</xsl:if>
</xsl:copy>
</xsl:template>

<!-- во всех строках где значение строка длинной 36 символов заменить тип на строку -->
<xsl:template match="ones:row/ones:Value">
<xsl:copy>
<xsl:choose>
<xsl:when test="string-length(current()) = 36">
<xsl:attribute name="xsi:type">
<xsl:value-of select="'xs:string'"/>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@* | node()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

Итоги:

  • Вполне работоспособный преобразователь;
  • Нет времени проверять, но это вероятнее всего быстрее, чем программное добавление колонки и обход таблицы значений в цикле с получением GUID-а по каждой ссылке.

Спасибо за внимание.

6 Comments

  1. wowik

    «Нет времени проверять, но это вероятнее всего быстрее…» — вот это как раз крайне интересно.

    Reply
  2. Поручик

    Методика интересная как пример или шаблон. Если потребуется заменить тип значения только в одной колонке с таким-то именем. Здесь что писать?

    <xsl:when test=»string-length(current()) = 36″>
    Reply
  3. A_Max

    +100500 работе с XSLT. Использую для преобразования xml в таблицу значений

    Reply
  4. Oldsad

    соглашусь с тем, что главное тут это замер быстродействия

    данный метод однозначно сложнее чем простой обход тз в цикле с получением гуидов

    когда критично быстродействие сам пользую вариант с получением гуидов компоновкой данных (программное создание компоновки на стороне источника через ком)

    Reply
  5. Olenevod

    (4) А не подскажете, есть какая-то специальная возможность в СКД получения GUID или вы говорите про вычисляемое поле, в котором можно получить GUID?

    Заранее благодарю.

    Reply
  6. Eret1k

    (5) Скорее всего имеется в виду вычисляемое поле с функцией XMLСтрока()

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *