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

XSLT中嵌套for-each循环继续主循环或从头遍历实现版本数据分组

XSLT嵌套循环遍历问题解决方案

你的需求本质是按ver字段对Row节点分组输出,两种遍历范围的实现方式如下:

首先修正原代码的语法错误

你现有代码存在几个语法问题会直接导致运行失败:

  • XML节点名大小写敏感:输入的节点是<Field>,XPath中写小写field会匹配不到
  • xsl:if的判断属性为test,不是select
  • 仅属性值动态插值需要用{},变量定义、XPath表达式中不需要加{}
  • 部分XPath表达式少闭合方括号,例如field[@name='ver'}应改为Field[@name='ver']

方案1:内层从XML起始位置遍历

内层for-each的select直接写根路径定位所有Row节点,再用currentVer过滤同版本节点即可:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Main>
    <xsl:for-each select="table/Row">
        <xsl:if test="Field[@name='isNewVersion'] = 1">
            <Data ver="{Field[@name='ver']}">
                <xsl:variable name="currentVer" select="Field[@name='ver']" />
                <!-- 内层从根开始遍历所有Row,过滤同版本 -->
                <xsl:for-each select="/table/Row[Field[@name='ver'] = $currentVer]">
                    <Sub id="{Field[@name='sub']}" />
                </xsl:for-each>
            </Data>
        </xsl:if>
    </xsl:for-each>
</Main>
</xsl:template>
</xsl:stylesheet>

方案2:内层从外层中断位置继续遍历

如果你的输入XML中同版本的Row节点是连续排列的(和你给出的测试数据结构一致),可以用以下写法只遍历后续同版本节点,执行效率更高:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Main>
    <xsl:for-each select="table/Row">
        <xsl:if test="Field[@name='isNewVersion'] = 1">
            <Data ver="{Field[@name='ver']}">
                <xsl:variable name="currentVer" select="Field[@name='ver']" />
                <!-- 包含当前Row + 后续所有同版本Row -->
                <xsl:for-each select="current() | following-sibling::Row[Field[@name='ver'] = $currentVer]">
                    <Sub id="{Field[@name='sub']}" />
                </xsl:for-each>
            </Data>
        </xsl:if>
    </xsl:for-each>
</Main>
</xsl:template>
</xsl:stylesheet>

更高性能的推荐方案:Muenchian分组

如果XML数据量较大,嵌套循环的性能会偏低,XSLT 1.0标准的分组实现为Muenchian分组,代码如下:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="rowByVer" match="Row" use="Field[@name='ver']" />
<xsl:template match="/">
<Main>
    <xsl:for-each select="table/Row[count(. | key('rowByVer', Field[@name='ver'])[1]) = 1]">
        <Data ver="{Field[@name='ver']}">
            <xsl:for-each select="key('rowByVer', Field[@name='ver'])">
                <Sub id="{Field[@name='sub']}" />
            </xsl:for-each>
        </Data>
    </xsl:for-each>
</Main>
</xsl:template>
</xsl:stylesheet>

以上三种方案输出的结果都和你预期的结构完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:06:02