You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让XSLT 2.0中key与tokenize函数结果保留拆分序列顺序

如何在XSLT 2.0中保留tokenize拆分后的原始顺序(避免key函数重排结果)

当使用XSLT 2.0的key()函数配合tokenize()拆分字符串时,返回的节点会按文档顺序排列,而非tokenize()拆分后的原始序列顺序。以下是问题示例及解决方法:

问题示例

输入文件

<?xml version="1.0" encoding="UTF-8"?>     
<a>     
<bd id="a">a</bd>     
<bd id="b">b</bd>     
<bd id="e">e</bd>     
<bd id="d">d</bd>     
</a>

原XSLT代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

     <xsl:key name="idcollect" match="*[@id]" use="@id" />
     <xsl:variable name="name" select="'d,b,e,a'"/>
    
     <xsl:template match="/">
      <xsl:for-each select="key('idcollect',tokenize($name,','))" >
         <xsl:copy-of select="."/>
     </xsl:for-each>
     </xsl:template>
    
</xsl:stylesheet>

当前输出(按文档顺序排列)

<?xml version="1.0" encoding="UTF-8"?><bd id="a">a</bd><bd id="b">b</bd><bd id="e">e</bd><bd id="d">d</bd>

期望输出(保留tokenize拆分后的原始顺序)

<?xml version="1.0" encoding="UTF-8"?><bd id="d">d</bd><bd id="b">b</bd><bd id="e">e</bd><bd id="a">a</bd>

解决方案

方法1:遍历tokenize后的key序列,逐个匹配节点

直接遍历tokenize()生成的原始序列,在循环内通过key()获取对应节点。这样循环顺序完全遵循tokenize拆分后的顺序,不会被文档顺序干扰。

修改后的XSLT代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:key name="idcollect" match="*[@id]" use="@id" />
    <xsl:variable name="name" select="'d,b,e,a'"/>
    
    <xsl:template match="/">
        <xsl:for-each select="tokenize($name, ',')">
            <xsl:copy-of select="key('idcollect', .)"/>
        </xsl:for-each>
    </xsl:template>
    
</xsl:stylesheet>

方法2:使用for-each-group按tokenize顺序映射(适配复杂场景)

如果需要处理重复key值或更复杂的节点匹配逻辑,可以通过for-each-group结合tokenize序列来强制保持顺序:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:variable name="name" select="'d,b,e,a'"/>
    <xsl:variable name="key-sequence" select="tokenize($name, ',')"/>
    
    <xsl:template match="/">
        <xsl:for-each-group select="//*[@id]" group-by="@id">
            <xsl:for-each select="$key-sequence[. = current-grouping-key()]">
                <xsl:copy-of select="current-group()"/>
            </xsl:for-each>
        </xsl:for-each-group>
    </xsl:template>
    
</xsl:stylesheet>

内容的提问来源于stack exchange,提问作者Muthukumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:01:20