#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»‘ Не могли бы вы рассказать, как выполняется это утверждение?