xslt 由定界符分割

xslt split by delimiter

我无法使用标记化 (xslt 2.0)

我有问题。我需要根据分隔符“\n”拆分值 "Test street\nStreet 2\nStreet3" 以生成

        <address1>Test street</address3>
        <address2>Street 2</address3>
        <address3>Street3</address3>

到目前为止我有这个:

<xsl:call-template name="tokenize">
    <xsl:with-param name="text" select="ns0:sObject/ens:BillingStreet"/>
</xsl:call-template>

<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="separator" select="'\n'"/>
    <xsl:choose>
        <xsl:when test="not(contains($text, $separator))">
            <Address>
                <xsl:value-of select="normalize-space($text)"/>
            </Address>
        </xsl:when>
        <xsl:otherwise>
            <Address>
                <xsl:value-of select="normalize-space(substring-before($text, $separator))"/>
            </Address>
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="substring-after($text, $separator)"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

它给了我这个:

        <Aaddress>Test street</Address>
        <Aaddress>Street 2</Address>
        <Aaddress>Street3</Address>

我尝试使用 position() 但它不起作用:

<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="separator" select="'\n'"/>
    <xsl:choose>
        <xsl:when test="not(contains($text, $separator))">
            <xsl:element name="Address{position()}">
                <xsl:value-of select="normalize-space($text)"/>
            </xsl:element>
        </xsl:when>
        <xsl:otherwise>
            <xsl:element name="Address{position()}">
                <xsl:value-of select="normalize-space(substring-before($text, $separator))"/>
            </xsl:element>
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="substring-after($text, $separator)"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

以上给出了我:

        <Address1>Test street</Address1>
        <Address1>Street 2</Address1>
        <Address1>Street3</Address1>

同样,我正在寻找的是:

        <Address1>Test street</Address1>
        <Address2>Street 2</Address2>
        <Address3>Street3</Address3>

有什么想法吗?

谢谢

'\n' 不是带换行符的字符串...使用字符引用 '&#xA;'

除此之外,请注意 position() 函数适用于当前上下文列表。这在调用命名模板后不会改变。因此,您的样式表片段取决于您未向我们展示的其他部分。

position() 在这里并不真正相关,因为它 returns 当前选定节点的位置。

您必须通过另一个参数来跟踪您的递归模板正在进行的迭代:

<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="separator" select="'\n'"/>
    <xsl:param name="pos" select="1" ></xsl:param>
    <xsl:choose>
        <xsl:when test="not(contains($text, $separator))">
            <xsl:element name="Address{$pos}">
                <xsl:value-of select="normalize-space($text)"/>
            </xsl:element>
        </xsl:when>
        <xsl:otherwise>
            <xsl:element name="Address{$pos}">
                <xsl:value-of select="normalize-space(substring-before($text, $separator))"/>
            </xsl:element>
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="substring-after($text, $separator)"/>
                <xsl:with-param name="pos" select="$pos + 1" />
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template> 

请注意,您可以稍微简化您的模板,以避免在创建 Address 元素时出现一些代码重复;像这样:

<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="separator" select="'\n'"/>
    <xsl:param name="pos" select="1" ></xsl:param>

    <xsl:element name="Address{$pos}">
        <xsl:value-of select="normalize-space(substring-before(concat($text, $separator), $separator))"/>
    </xsl:element>
    <xsl:if test="contains($text, $separator)" >
        <xsl:call-template name="tokenize">
            <xsl:with-param name="text" select="substring-after($text, $separator)"/>
            <xsl:with-param name="pos" select="$pos + 1" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>