XSL: построить массив из строки с разделителями

У меня есть строка, в которой данные разделяются разделителем типа "|" и присутствует в переменной. Я хотел бы создать массив в XSL, разделив указанную выше строку на основе разделителя и хотел бы получить доступ к тому же в цикле for.

Пожалуйста, помогите мне в этом отношении. Пожалуйста, дайте мне знать, если кому-то нужна дополнительная информация.

String is "Test1|Test2|Test3|Test4" и хотел бы получить переменную TEMP, которая будет массивом данных из строки и хотела бы получить доступ как TEMP[index].

Я попытался использовать функцию tokenize после ввода от участников форума, чтобы получить значения из строки, но не был успешным. Я не получаю строковые значения в цикле.

<xsl:variable name="temp" xmlns:str="http://exslt.org/strings" select="str:tokenize(normalize-space(' Test1$,$Test2$,$Test3$,$Test4 '),'$,$')"/>
<xsl:for-each xmlns:str="http://exslt.org/strings" select="str:split(normalize-space(' 1$,$2$,$3$,$4$,$5$,$6 '),'$,$')">
    <xsl:variable name="index" select="position()"/>
    <xsl:value-of select="$temp[$index]"/>
</xsl:for-each>

С уважением, Lakshman

Ответ 1

Строка "Test1|Test2|Test3|Test4" и хочет получить переменную TEMP, который будет массивом данных из строки и хотел бы для доступа к TEMP[index].

+1 для хорошего вопроса.

Преобразование XSLT 1.0:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vrtfTokens">
  <xsl:apply-templates/>
 </xsl:variable>

 <xsl:variable name="vTokens" select=
   "ext:node-set($vrtfTokens)/*"/>
 <xsl:template match="/">
  <xsl:for-each select=
   "document('')//node()[not(position() > count($vTokens))]
   ">
   <xsl:variable name="vPos" select="position()"/>
    <xsl:copy-of select="$vTokens[$vPos+0]"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="text()" name="split">
  <xsl:param name="pText" select="."/>

  <xsl:if test="string-length($pText)">
   <xsl:variable name="vToken" select=
    "substring-before(concat($pText,'|'), '|')"/>
   <s><xsl:value-of select="$vToken"/></s>

   <xsl:call-template name="split">
    <xsl:with-param name="pText" select=
    "substring-after($pText, '|')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

при применении к этому XML-документу:

<t>Test1|Test2|Test3|Test4</t>

создает переменную vTokens, которая содержит элементы с именем s, каждый из которых имеет в качестве своего единственного текстового дочернего токена из строки '|' -delimited "Test1|Test2|Test3|Test4".

Затем преобразование выводит каждый из этих элементов s, используя "индекс".

Полученный, правильный результат получается:

<s>Test1</s>
<s>Test2</s>
<s>Test3</s>
<s>Test4</s>

Если нам нужны только сами маркеры (строки), мы будем использовать:

string($vTokens[someIndex])

Ответ 2

Это не будет массив, а последовательность, и у вас должен быть процессор XSLT 2.0. Вы можете использовать функцию tokenize():

<xsl:variable name="temp" as="xs:string*" select="tokenize('Test1|Test2|Test3|Test4','\|')"/>

Вы также можете передать строковую переменную в качестве первого аргумента tokenize.

Затем вы используете:

<xsl:value-of select="$temp[$index]"/>

EDIT: достичь этого в xslt 1.0 невозможно, если вы не используете какое-то расширение.

Ответ 3

Эта задача называется tokenizing, в XSLT 2.0 вы можете использовать tokenize('Test1|Test2|Test3|Test4', '\|'), с XSLT 1.0 вы можете использовать расширение, например http://www.exslt.org/str/functions/tokenize/index.html.

Ответ 4

Я пробую это, я изменил код "Dimitre Novatchev" и работает для меня: (пожалуйста, извините меня за мой английский)

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:msxsl="urn:schemas-microsoft-com:xslt"
            exclude-result-prefixes="msxsl">

<xsl:template match="/*">
        <xsl:variable name="_keywords">
            <xsl:call-template name="split-to-values">
                <xsl:with-param name="_text" select="Keywords-comma-separated"/>
            </xsl:call-template>
        </xsl:variable>

        <xsl:for-each select="msxsl:node-set($_keywords)/value">
            <xsl:variable name="_keyword" select="."/>
            <!-- ANY CODE -->
        </xsl:for-each>
</xsl:template>

<xsl:template match="text()" name="split-to-values">
    <xsl:param name="_text"/>

    <xsl:if test="string-length($_text)">
        <xsl:variable name="_value" select="substring-before($_text, ',')"/>
        <xsl:variable name="_next" select="substring-after($_text, ',')"/>
        <value>
            <xsl:value-of select="$_value"/>
        </value>

        <xsl:call-template name="split-to-values">
            <xsl:with-param name="_text" select="$_next"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

Я надеюсь, что это поможет вам

@Bugude ask

У меня есть строка, в которой данные разделяются разделителем типа "|" а также присутствует в переменной. Я хотел бы создать массив в XSL путем деления указанной строки на основе разделителя и хотел бы получить доступ к одному и тому же в цикле for

Тогда строка может быть: "alfa, beta, gama, delta"

Разделитель представлен в переменной:

<xsl:variable name="_delimiter">,</xsl:variable>

Я изменил шаблон как:

<xsl:template match="text()" name="split-to-values">
    <xsl:param name="_text"/>
    <xsl:param name="_delimiter"/>

    <xsl:if test="string-length($_text)">
        <xsl:variable name="_value" select="substring-before($_text, $_delimiter)"/>
        <xsl:variable name="_next" select="substring-after($_text, $_delimiter)"/>
        <value>
            <xsl:value-of select="$_value"/>
        </value>

        <xsl:call-template name="split-to-values">
            <xsl:with-param name="_text" select="$_next"/>
            <xsl:with-param name="_delimiter" select="$_delimiter"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

И мы можем получить доступ к узлам как похожий массив с a для

<xsl:template match="/*">
        <!-- _keyword as set a node -->
        <xsl:variable name="_keywords">
            <xsl:call-template name="split-to-values">
                <xsl:with-param name="_text" select="'alfa,beta,gama,delta'"/>
                <xsl:with-param name="_delimiter" select="$_delimiter"/>
            </xsl:call-template>
        </xsl:variable>

        <xsl:for-each select="msxsl:node-set($_keywords)/value">
            <xsl:variable name="_keyword" select="."/>
            <!-- ANY CODE -->
            <xsl:value-of select="$_keyword"/>
        </xsl:for-each>
</xsl:template>