Как реализовать динамический массив в xslt

#arrays #xslt #dynamic-arrays

#массивы #xslt #динамические массивы

Вопрос:

Мне нужно объявить массив в моем шаблоне xslt, например, (псевдокод) myarray = [] // объявление пустого массива, затем мне нужно поместить несколько строк, как показано ниже, по одной за раз myarray = [doc] // put a string into the array , затем мне нужно извлечь каждый элемент в массиве и сравнить с другой строкой, например foreach myarray[i]{
tempstring = myarray[i]
test=compare(somes-tring,tempstring)
then
do some action
break
else
continue loop till all element in array are compared

 ` }`
  

Затем, если ни одна строка в массиве не соответствует «некоторой строке», добавьте некоторую строку в массив.

После нескольких шагов итерации заканчивается пустой myarray

Комментарии:

1. Почти наверняка проблема XY . В XSLT нет понятия массивов, и, хотя, вероятно, их можно смоделировать, поскольку это язык, полный по Тьюрингу, это было бы чрезвычайно сложно и неинтуитивно по сравнению с любым решением, которое использует язык так, как он предназначен для использования. Я настоятельно рекомендую вам перефразировать свой вопрос, чтобы описать реальную проблему, которую вы пытаетесь решить.

2. XSLT 3 с поддержкой XPath 3.1 имеет тип данных array, но неясно, где / нужно ли вам это. Единственная итерация в XSLT 3 заключается xsl:iterate в том, что вы можете передавать массив как xsl:param , но всегда учитывая, что это любая операция, которая просто вернет новый массив. В XSLT 3 также есть аккумуляторы, которые могут помочь сохранить и изменить значение во время обработки дерева документов.

3. Расскажите нам, каковы входные и выходные данные вашего преобразования и как они связаны: не говорите нам, как бы вы решили проблему на другом (процедурном) языке программирования.

4. @Мартин Хоннен, я исправлен!

5. @ Martin Honnen Да, мне нужен тот же XSLT 3 с реализацией массива XPath 3.1 с помещением, получением и очисткой массива для повторного использования. Мое требование состоит в том, чтобы использовать массив для сравнения строк, чтобы увидеть, существует ли строка уже или нет, и если существует, то выполните какое-либо действие, иначе продолжайте добавлять сравниваемую строку в массив для следующего сравнения строк

Ответ №1:

Вы можете объявить динамический массив следующим образом:

 <xsl:variable name="myarray">
    <item ord="-1" index="-1"/>
</xsl:variable>
  

Код с некоторыми тестами (я предполагаю, что вы уже научились программировать циклы в XSLT, поэтому я не буду вдаваться в подробности здесь):

Код

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:variable name="myarray">
        <item ord="-1" index="-1"/>
    </xsl:variable>
        
    <xsl:template match="/">
        <xsl:param name="index"/>
        <xsl:param name="value"/>
        <xsl:if test="./*[@index = $index] and $value">
            <xsl:variable name="myOrd" select="./*[@index = $index]/@ord"/>
            <xsl:copy-of select="./*[@ord amp;< $myOrd]"/>
            <item ord="{./*[@index = $index]/@ord}" index="{$index}"><xsl:value-of select="$value"/></item>
            <xsl:copy-of select="./*[@ord amp;> $myOrd]"/>
        </xsl:if>
        <xsl:if test="./*[@index = $index] and not($value)">
            <xsl:variable name="myOrd" select="./*[@index = $index]/@ord"/>
            <xsl:copy-of select="./*[@ord amp;< $myOrd]"/>
            <xsl:copy-of select="./*[@ord amp;> $myOrd]"/>
        </xsl:if>
        <xsl:if test="not(./*[@index = $index])">
            <xsl:variable name="maxOrd" select="number(./*[last()]/@ord   1)"/>
            <xsl:copy-of select="./*[@ord amp;< $maxOrd]"/>
            <item ord="{$maxOrd}" index="{$index}"><xsl:value-of select="$value"/></item>
        </xsl:if>
    </xsl:template>

    <xsl:template name="test"> 

        <!-- start of the loop -->

        <!-- iteration step 1 -->
        <xsl:variable name="myarray"> 
            <xsl:apply-templates select="$myarray">
                <xsl:with-param name="index" select="3"/>
                <xsl:with-param name="value" select="'value at 3'"/>
            </xsl:apply-templates>
        </xsl:variable>
        <xsl:apply-templates select="$myarray" mode="dump"/>
        <dump step="1">
            <xsl:copy-of select="$myarray/*[@ord amp;>= 0]"/>
        </dump>

        <!-- iteration step 2 -->
        <xsl:variable name="myarray"> 
            <xsl:apply-templates select="$myarray">
                <xsl:with-param name="index" select="15"/>
                <xsl:with-param name="value" select="'value at 15'"/>
            </xsl:apply-templates>
        </xsl:variable>
        <xsl:apply-templates select="$myarray" mode="dump"/>
        <dump step="2">
            <xsl:copy-of select="$myarray/*[@ord amp;>= 0]"/>
        </dump>

        <!-- iteration step 3 -->
        <xsl:variable name="myarray"> 
            <xsl:apply-templates select="$myarray">
                <xsl:with-param name="index" select="5"/>
                <xsl:with-param name="value" select="'value at 5'"/>
            </xsl:apply-templates>
        </xsl:variable>
        <xsl:apply-templates select="$myarray" mode="dump"/>
        <dump step="3">
            <xsl:copy-of select="$myarray/*[@ord amp;>= 0]"/>
        </dump>

        <!-- iteration step 4 -->
        <xsl:variable name="myarray"> 
            <xsl:apply-templates select="$myarray">
                <xsl:with-param name="index" select="5"/>
                <xsl:with-param name="value" select="'newValue at 5'"/>
            </xsl:apply-templates>
        </xsl:variable>
        <xsl:apply-templates select="$myarray" mode="dump"/>
        <dump step="4">
            <xsl:copy-of select="$myarray/*[@ord amp;>= 0]"/>
        </dump>
        
        <!-- iteration step 5 -->
        <xsl:variable name="myarray"> 
            <xsl:apply-templates select="$myarray">
                <xsl:with-param name="index" select="15"/>
                <xsl:with-param name="value" select="''"/>
            </xsl:apply-templates>
        </xsl:variable>
        <xsl:apply-templates select="$myarray" mode="dump"/>
        <dump step="5">
            <xsl:copy-of select="$myarray/*[@ord amp;>= 0]"/>
        </dump>

        <!-- end of the loop -->
    </xsl:template> 

    <xsl:template match="/" mode="dump">
        <xsl:message>Array:</xsl:message>
        <xsl:for-each select="*[@index amp;> -1]">
            <xsl:sort select="@index" data-type="number"/>
            <xsl:message>
                <xsl:value-of select="concat('array[',@index,'] = ',.)"/>
            </xsl:message>
        </xsl:for-each>
    </xsl:template> 
    
</xsl:stylesheet>
  

Комментарий

  • шаг 1: установите значение по индексу 3
  • шаг 2: установите значение с индексом 15
  • шаг 3: установите значение по индексу 5
  • шаг 4: установите значение по индексу 5 (новое значение)
  • шаг 5: удалите значение в индексе 15

Вывод на консоль

 Array:
array[3] = value at 3
Array:
array[3] = value at 3
array[15] = value at 15
Array:
array[3] = value at 3
array[5] = value at 5
array[15] = value at 15
Array:
array[3] = value at 3
array[5] = newValue at 5
array[15] = value at 15
Array:
array[3] = value at 3
array[5] = newValue at 5
  

Вывод XML

   <?xml version="1.0" encoding="UTF-8"?>
  <dump step="1">
     <item ord="0" index="3">value at 3</item>
  </dump>
  <dump step="2">
     <item ord="0" index="3">value at 3</item>
     <item ord="1" index="15">value at 15</item>
  </dump>
  <dump step="3">
     <item ord="0" index="3">value at 3</item>
     <item ord="1" index="15">value at 15</item>
     <item ord="2" index="5">value at 5</item>
  </dump>
  <dump step="4">
     <item ord="0" index="3">value at 3</item>
     <item ord="1" index="15">value at 15</item>
     <item ord="2" index="5">newValue at 5</item>
  </dump>
  <dump step="5">
     <item ord="0" index="3">value at 3</item>
     <item ord="2" index="5">newValue at 5</item>
  </dump>
  

Комментарии:

1. Спасибо за ваш подробный ответ .. ваша версия таблицы стилей 1.0 Можем ли мы использовать версию 3.0 с функциями массива xpath, указанными ниже, с использованием метода ввода и получения массива в нем? w3.org/TR/xpath-functions-31/#func-array-size Кстати, я не смог разрешить это утверждение в вашем сообщении ‘select=»./* [@index = $index]/@ord»‘ Не могли бы вы рассказать, как выполняется это утверждение?