如何在单循环中读取2个逗号分隔的字符串-XSLT

如何在单循环中读取2个逗号分隔的字符串-XSLT,xslt,xslt-1.0,ibm-datapower,exslt,Xslt,Xslt 1.0,Ibm Datapower,Exslt,我有以下两个变量,它们在不同的XSLT变量中有多个逗号分隔的字符串值 Variable_01 : 88888,777777 Variable_02 : abc,xyz 现在我正在寻找以下输出 [{"Group":"88888", "Name":"abc"},{"Group":"777777", "Name":"xyz"}] 请您帮助我上述输出的正确XSLT代码是什么。以下是一种方法: XSLT2.0 <xsl:stylesheet version="2.0" xmlns:xsl="h

我有以下两个变量,它们在不同的XSLT变量中有多个逗号分隔的字符串值

Variable_01 : 88888,777777
Variable_02 : abc,xyz
现在我正在寻找以下输出

[{"Group":"88888", "Name":"abc"},{"Group":"777777", "Name":"xyz"}]

请您帮助我上述输出的正确XSLT代码是什么。

以下是一种方法:

XSLT2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:variable name="Variable_01">88888,777777</xsl:variable>
<xsl:variable name="Variable_02">abc,xyz</xsl:variable>

<xsl:template match="/">
    <xsl:text>[</xsl:text>
    <xsl:for-each select="tokenize($Variable_01, ',')">
        <xsl:variable name="i" select="position()"/>
        <xsl:text>{"Group":"</xsl:text>
        <xsl:value-of select="." />
        <xsl:text>", "Name":"</xsl:text>
        <xsl:value-of select="tokenize($Variable_02, ',')[$i]" />
        <xsl:text>"}</xsl:text>
        <xsl:if test="position()!=last()">
            <xsl:text>,</xsl:text>
        </xsl:if>
    </xsl:for-each>
    <xsl:text>]</xsl:text>
</xsl:template>

</xsl:stylesheet>


演示

在XSLT 3中,每对都具有高阶函数
,并支持JSON映射和数组

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="3.0">

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

    <xsl:param name="Variable_01" as="xs:string">88888,777777</xsl:param>
    <xsl:param name="Variable_02" as="xs:string">abc,xyz</xsl:param>

    <xsl:template match="/" name="xsl:initial-template">
        <xsl:sequence 
         select="array { 
                   for-each-pair(
                     tokenize($Variable_01, ','),
                     tokenize($Variable_02, ','),
                     function($a, $b) { map { 'Group' : $a, 'Name' : $b } }
                   )
                 }"/>
    </xsl:template>

</xsl:stylesheet>

最后,在没有JSON数组和映射支持的XSLT 2中,您可以使用相同的方法来创建文本输出:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="2.0">

    <xsl:output method="text"/>

    <xsl:function name="mf:object-for-each-pair" as="xs:string*">
      <xsl:param name="seq1"/>
      <xsl:param name="seq2"/>
      <xsl:if test="exists($seq1) and exists($seq2)">
        <xsl:sequence select="concat('{ &quot;Group&quot; : &quot;', $seq1[1], '&quot;, &quot;Name&quot; : &quot;', $seq2[1], '&quot; }')"/>
        <xsl:sequence select="mf:object-for-each-pair(subsequence($seq1, 2), subsequence($seq2, 2))"/>
      </xsl:if>
    </xsl:function>

    <xsl:param name="Variable_01" as="xs:string">88888,777777</xsl:param>
    <xsl:param name="Variable_02" as="xs:string">abc,xyz</xsl:param>

    <xsl:template match="/">
        <xsl:text>[ </xsl:text>
        <xsl:value-of select="mf:object-for-each-pair(tokenize($Variable_01, ','), tokenize($Variable_02, ','))" separator=", "/>
        <xsl:text> ]</xsl:text>
    </xsl:template>

</xsl:stylesheet>

88888,777777
abc,xyz
[ 
]

这有点粗糙。但它完成了任务

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

    <xsl:output method="text" encoding="UTF-8"/>

    <xsl:variable name="Variable_01">88888,777777</xsl:variable>
    <xsl:variable name="Variable_02">abc,xyz</xsl:variable>

    <xsl:template match="/">
        <xsl:text>[</xsl:text>
        <xsl:call-template name="tokenizeString">
            <!-- store anything left in another variable -->
            <xsl:with-param name="list" select="$Variable_01"/>
            <xsl:with-param name="list2" select="$Variable_02"/>
            <xsl:with-param name="delimiter" select="','"/>
        </xsl:call-template>
        <xsl:text>]</xsl:text>
    </xsl:template>

    <xsl:template name="tokenizeString">
        <!--passed template parameter -->
        <xsl:param name="list"/>
        <xsl:param name="list2"/>
        <xsl:param name="delimiter"/>
        <xsl:choose>
            <xsl:when test="contains($list, $delimiter)">
                <!-- get everything in front of the first delimiter -->
                <xsl:text>{"Group":"</xsl:text>
                <xsl:value-of select="substring-before($list,$delimiter)"/>
                <xsl:text>", "Name":"</xsl:text>
                <xsl:call-template name="tokenizeAnother">
                    <xsl:with-param name="list2" select="$list2"/>
                    <xsl:with-param name="delimiter" select="$delimiter"/>
                </xsl:call-template>
                <xsl:text>"},</xsl:text>
                <xsl:call-template name="tokenizeString">
                    <!-- store anything left in another variable -->
                    <xsl:with-param name="list" select="substring-after($list,$delimiter)"/>
                    <xsl:with-param name="list2" select="substring-after($list2,$delimiter)"/>
                    <xsl:with-param name="delimiter" select="$delimiter"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>{"Group":"</xsl:text>
                <xsl:value-of select="$list"/>
                <xsl:text>", "Name":"</xsl:text>
                <xsl:call-template name="tokenizeAnother">
                    <xsl:with-param name="list2" select="$list2"/>
                    <xsl:with-param name="delimiter" select="$delimiter"/>
                </xsl:call-template>
                <xsl:text>"}</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="tokenizeAnother">
        <xsl:param name="list2"/>
        <xsl:param name="delimiter"/>
        <xsl:choose>
            <xsl:when test="contains($list2, $delimiter)">
                <!-- get everything in front of the first delimiter -->
                <xsl:value-of select="substring-before($list2,$delimiter)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$list2"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

88888,777777
abc,xyz
[
]
{“集团”:
,“名称”:
"},
{“集团”:
,“名称”:
"}

查看它的实际操作。

最后,这里是一个不需要任何扩展函数的纯XSLT 1.0解决方案:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:variable name="Variable_01">88888,777777</xsl:variable>
<xsl:variable name="Variable_02">abc,xyz</xsl:variable>

<xsl:template match="/">
    <xsl:text>[</xsl:text>
    <xsl:call-template name="tokenize-to-pairs">
        <xsl:with-param name="left-text" select="$Variable_01"/>
        <xsl:with-param name="right-text" select="$Variable_02"/>
    </xsl:call-template>
    <xsl:text>]</xsl:text>
</xsl:template>

<xsl:template name="tokenize-to-pairs">
    <xsl:param name="left-text"/>
    <xsl:param name="right-text"/>
    <xsl:param name="delimiter" select="','"/>
    <!-- output -->
    <xsl:text>{"Group":"</xsl:text>
    <xsl:value-of select="substring-before(concat($left-text, $delimiter), $delimiter)" />
    <xsl:text>", "Name":"</xsl:text>
    <xsl:value-of select="substring-before(concat($right-text, $delimiter), $delimiter)" />
    <xsl:text>"}</xsl:text>
    <!-- recursive call -->
    <xsl:if test="contains($left-text, $delimiter)">
        <xsl:text>,</xsl:text>
        <xsl:call-template name="tokenize-to-pairs">
            <xsl:with-param name="left-text" select="substring-after($left-text, $delimiter)"/>
            <xsl:with-param name="right-text" select="substring-after($right-text, $delimiter)"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

88888,777777
abc,xyz
[
]
{“集团”:
,“名称”:
"}
,

顺便问一下,变量是如何设置的?它们是否只包含静态字符串或作为参数传入的值?或者它们是由XSLT使用输入XML中的值设置的?谢谢好吧,
head()
tail()
在XSLT 3.0中是新的。@michael.hor257k,是的,你是对的,我忽略了在我尝试将XSLT 3代码变形为XSLT 2时,还需要删除
name=“xsl:initial template”
。感谢Martin的快速响应,我的问题仍然没有解决,现在我收到错误消息tokenize函数无法识别感谢Michael的快速响应我的问题仍未解决,现在我收到错误消息tokenize函数无法识别recognize@MayurGaikwad当您的处理器不支持XSLT 2.0时,为什么将问题标记为XSLT 2.0如果您使用的是IBM DataPower,那么您应该能够使用EXSLT
str:tokenize()
extension函数。为此向Michael道歉,我刚刚更正了此标记。如果你有主意的话,你能帮忙吗me@MayurGaikwad我已经做到了。请阅读EXSLT站点或DataPower手册中有关该功能的帮助。谢谢Michael:)我的问题已经解决。它确实可以更简单,正如我希望在第二次回答中所示。
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" encoding="UTF-8"/>

    <xsl:variable name="Variable_01">88888,777777</xsl:variable>
    <xsl:variable name="Variable_02">abc,xyz</xsl:variable>

    <xsl:template match="/">
        <xsl:text>[</xsl:text>
        <xsl:call-template name="tokenizeString">
            <!-- store anything left in another variable -->
            <xsl:with-param name="list" select="$Variable_01"/>
            <xsl:with-param name="list2" select="$Variable_02"/>
            <xsl:with-param name="delimiter" select="','"/>
        </xsl:call-template>
        <xsl:text>]</xsl:text>
    </xsl:template>

    <xsl:template name="tokenizeString">
        <!--passed template parameter -->
        <xsl:param name="list"/>
        <xsl:param name="list2"/>
        <xsl:param name="delimiter"/>
        <xsl:choose>
            <xsl:when test="contains($list, $delimiter)">
                <!-- get everything in front of the first delimiter -->
                <xsl:text>{"Group":"</xsl:text>
                <xsl:value-of select="substring-before($list,$delimiter)"/>
                <xsl:text>", "Name":"</xsl:text>
                <xsl:call-template name="tokenizeAnother">
                    <xsl:with-param name="list2" select="$list2"/>
                    <xsl:with-param name="delimiter" select="$delimiter"/>
                </xsl:call-template>
                <xsl:text>"},</xsl:text>
                <xsl:call-template name="tokenizeString">
                    <!-- store anything left in another variable -->
                    <xsl:with-param name="list" select="substring-after($list,$delimiter)"/>
                    <xsl:with-param name="list2" select="substring-after($list2,$delimiter)"/>
                    <xsl:with-param name="delimiter" select="$delimiter"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>{"Group":"</xsl:text>
                <xsl:value-of select="$list"/>
                <xsl:text>", "Name":"</xsl:text>
                <xsl:call-template name="tokenizeAnother">
                    <xsl:with-param name="list2" select="$list2"/>
                    <xsl:with-param name="delimiter" select="$delimiter"/>
                </xsl:call-template>
                <xsl:text>"}</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="tokenizeAnother">
        <xsl:param name="list2"/>
        <xsl:param name="delimiter"/>
        <xsl:choose>
            <xsl:when test="contains($list2, $delimiter)">
                <!-- get everything in front of the first delimiter -->
                <xsl:value-of select="substring-before($list2,$delimiter)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$list2"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:variable name="Variable_01">88888,777777</xsl:variable>
<xsl:variable name="Variable_02">abc,xyz</xsl:variable>

<xsl:template match="/">
    <xsl:text>[</xsl:text>
    <xsl:call-template name="tokenize-to-pairs">
        <xsl:with-param name="left-text" select="$Variable_01"/>
        <xsl:with-param name="right-text" select="$Variable_02"/>
    </xsl:call-template>
    <xsl:text>]</xsl:text>
</xsl:template>

<xsl:template name="tokenize-to-pairs">
    <xsl:param name="left-text"/>
    <xsl:param name="right-text"/>
    <xsl:param name="delimiter" select="','"/>
    <!-- output -->
    <xsl:text>{"Group":"</xsl:text>
    <xsl:value-of select="substring-before(concat($left-text, $delimiter), $delimiter)" />
    <xsl:text>", "Name":"</xsl:text>
    <xsl:value-of select="substring-before(concat($right-text, $delimiter), $delimiter)" />
    <xsl:text>"}</xsl:text>
    <!-- recursive call -->
    <xsl:if test="contains($left-text, $delimiter)">
        <xsl:text>,</xsl:text>
        <xsl:call-template name="tokenize-to-pairs">
            <xsl:with-param name="left-text" select="substring-after($left-text, $delimiter)"/>
            <xsl:with-param name="right-text" select="substring-after($right-text, $delimiter)"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>