XSL: построение массива из строки с разделителями - PullRequest
12 голосов
/ 29 ноября 2011

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

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

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

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

<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

Ответы [ 4 ]

14 голосов
/ 30 ноября 2011

String имеет значение "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, каждый из которых имеет в качестве единственного текстового дочернего элемента токен из строки с ограничением '|' "Test1|Test2|Test3|Test4".

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

Требуется правильный результат :

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

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

string($vTokens[someIndex])
9 голосов
/ 29 ноября 2011

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

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

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

Тогда вы используете:

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

РЕДАКТИРОВАТЬ: достичь этого в xslt 1.0 невозможно, если вы не используете какое-либо расширение.

3 голосов
/ 29 ноября 2011

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

1 голос
/ 09 июня 2017

Я пытаюсь это сделать, я изменил код "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

Тогда строка может быть: «альфа, бета, гама, дельта»

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

<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>

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

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...