【问题标题】:Continue Main Looping In Nested For-each In XSLT在 XSLT 中的嵌套 For-each 中继续主循环
【发布时间】:2021-12-27 07:20:42
【问题描述】:

我正在尝试做一些看似不合理的事情,但我有这样的要求。

希望创建一个嵌套的 for-each 循环,该循环将从外部 for-each 继续或重新开始,如下例所示。

以下是输入 xml,此输入表示我正在使用的结构,但带有虚拟数据。 XML:

<table>
  <Row>
    <Field name="ver">1</field>
    <Field name="isNewVersion">1</field>
    <Field name="sub">a</field>
  </Row>
  <Row>
    <Field name="ver">1</field>
    <Field name="isNewVersion">0</field>
    <Field name="sub">b</field>
  </Row>
  <Row>
    <Field name="ver">1</field>
    <Field name="isNewVersion">0</field>
    <Field name="sub">c</field>
  </Row>
  <Row>
    <Field name="ver">2</field>
    <Field name="isNewVersion">1</field>
    <Field name="sub">x</field>
  </Row>
    <Row>
    <Field name="ver">2</field>
    <Field name="isNewVersion">0</field>
    <Field name="sub">y</field>
  </Row>
</table>

外部 for-each 工作正常,但似乎无法使嵌套的 for-each 工作。有没有办法让我迭代:
其余的 &lt;field&gt; 标签(从外部 for-each 留下的地方继续)

从整个输入xml的开头开始

XSLT:

<?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 select="field[@name='isNewVersion'] = 1">   <!--check if first sub per new version-->
        
            <Data ver="{field[@name='ver'}">
                
                <xsl:variable name="currentVer" select="{field[@name='ver'}" /> <!--saved for nested for-each-->                
                <xsl:for-each select="..."> <!--This is the problem, would like to iterate from the start of xml-->
                
                    <xsl:if select="{field[@name='ver'] = currentVer}"> <!--check if came to new version-->
                    
                        <Sub id="{field[@name='sub']}" />

                    </xsl:if>
                    
                </xsl:for-each>
                
            </Data>
        </xsl:if>
        
        
    </xsl:for-each>

</Main>

</xsl:template>

</xsl:stylesheet>

这就是我希望最终(输出)xml 的样子。 我想要的输出:

<Main>
    <Data ver="1">
        <Sub id="a" />
        <Sub id="b" />
        <Sub id="c" />
    </Data>
    <Data ver="2">
        <Sub id="x" />
        <Sub id="y" />
    </Data>
</Main>

感谢您的帮助:)

【问题讨论】:

  • 您在用非常程序化的术语描述您想要实现的目标,结果让您的生活变得困难。不要从循环、“重新开始”、“离开”和“继续”的角度来思考。从映射的角度思考:输出中的事物集如何(在功能上)与输入中的事物集相关。
  • 话虽如此,这实际上是一个简单的分组问题,知道了这一点,您可以找到大量关于如何在 XSLT 中解决分组问题的信息。在 XSLT 2.0+ 中比在 XSLT 1.0 中容易得多。
  • 因为分组问题非常普遍(尽管人们通常不认识它们),所以我将其作为分组中更受欢迎的问题/答案之一的副本关闭。
  • 这不完全是一个分组问题。记录已经分组,因为每个组都有一个独特且可识别的“领导者”记录。剩下的就是收集属于当前组的记录。
  • 感谢@MichaelKay 和michael.hor257k,我确实没有意识到这个非常简单的分组问题,我也没有提到我只能使用XSLT 1.0。但是,我确实在算法上解决了这个问题,使用一个嵌套循环和一个变量,只是从外部循环遍历相同的 xpath。不过,这个解决方案是错误的,我将对其进行更改以更好地适应 XSLT 范例。

标签: xml xslt foreach


【解决方案1】:

试试这个方法:

XSLT 1.0

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

<xsl:key name="row-by-ver" match="Row" use="field[@name='ver']" />

<xsl:template match="/table">
    <Main>
        <xsl:for-each select="Row[field[@name='isNewVersion'] = 1]">
            <xsl:variable name="version" select="field[@name='ver']" />
            <Data ver="{$version}">
                <xsl:for-each select="key('row-by-ver', $version)">
                    <Sub id="{field[@name='sub']}" />
                </xsl:for-each>
            </Data>
        </xsl:for-each>
    </Main>
</xsl:template>

</xsl:stylesheet>

注意

XML 区分大小写。 fieldField 不同,您的输入将在以下每一行产生错误:

<Field name="x">y</field>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-19
    • 2013-12-17
    • 2014-03-20
    • 2015-05-27
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多