xml XSLT - 在嵌套的 for-each 中查找 position()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24758895/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 12:04:11  来源:igfitidea点击:

XSLT - find position() when inside a nested for-each

xmlxsltforeachpositionxslt-2.0

提问by danw

I'm using XSLT to perform a transformation on some fairly complex XML. In order to achieve the output I need to, I've had to create a nested for loop something like the following:

我正在使用 XSLT 对一些相当复杂的 XML 执行转换。为了实现我需要的输出,我必须创建一个嵌套的 for 循环,如下所示:

Source XML

源 XML

<root>
  <element1>
    <child>
      <aaa></aaa>
      <bbb></bbb>
    </child>
  </element1>
  <element2/>
  <element3/>
  <element3/>
  <element3/>
</root>

XSLT

XSLT

<xsl:for-each select="element3">
  <!-- Do some stuff -->

  <xsl:for-each select="../element1/child/*">
    <!-- Do some more stuff -->
  </xsl:for-each>
</xsl:for-each>

Problem

问题

What I'm trying to do here is whilst in my nested loop (on ../element1/child/*) - I'd like to find out:

我在这里尝试做的是 while 在我的嵌套循环中 (on ../element1/child/*) - 我想知道:

  1. The position of the element I'm currently looping - if, for example, I was currently focused on <bbb>then this position (I think) would be '1'
  2. The position of the parent loop (on element3) - so if, for example, I was on the third instance of <element3>and then looping through ../element1/child/*and was focused on <aaa>- the two values I would be after would be '2' and '0'.
  1. 我当前循环的元素的位置 - 例如,如果我当前专注于<bbb>那么这个位置(我认为)将是“1”
  2. 父循环的位置 (on element3) - 例如,如果我在第三个实例上<element3>,然后循环../element1/child/*并专注于<aaa>- 我将要追求的两个值将是“2”和“0”。

Ideally, I'd like to be able to assign these values to a variable. I've tried using the position()notation like below but this doesn't seem to be working.

理想情况下,我希望能够将这些值分配给一个变量。我试过使用如下position()表示法,但这似乎不起作用。

<xsl:for-each select="../element1/child/*">
  <xsl:variable name="postion_current_loop" select="position()"/>
  <xsl:variable name="postion_parent_loop" select="??????"/>
  <!-- Do some more stuff -->
</xsl:for-each>

If anyone has any ideas on how I could achieve this that would be greatly appreciated! I'm using XSLT 2.0, but am open to solutions using XSLT 1.0 if need be. Thanks in advance.

如果有人对我如何实现这一目标有任何想法,将不胜感激!我正在使用 XSLT 2.0,但如果需要,我对使用 XSLT 1.0 的解决方案持开放态度。提前致谢。

回答by michael.hor257k

You should try modifying your input to:

您应该尝试将输入修改为:

<root>
  <element1>
    <child>
      <aaa>1a</aaa>
      <bbb>2a</bbb>
    </child>
  </element1>
  <element2/>
  <element3>3a</element3>
  <element3>3b</element3>
  <element3>3c</element3>
</root>

then see what you get with:

然后看看你得到了什么:

<xsl:template match="/">
    <test>
        <xsl:for-each select="root/element3">
        <xsl:variable name="parent-position" select="position()" />
        <xsl:variable name="parent-value" select="." />
            <xsl:for-each select="../element1/child/*">
                <item value="{.}" parent-value="{$parent-value}" parent-position="{$parent-position}" position="{position()}"/>
            </xsl:for-each>
        </xsl:for-each>    
    </test>
</xsl:template>

回答by Nic Gibson

I've added some id attributes to your input so you can see which node is getting processed where so my input looked like:

我在您的输入中添加了一些 id 属性,以便您可以查看正在处理哪个节点的位置,因此我的输入如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <element1 id="e1-1">
        <child>
            <aaa id="e1-a"></aaa>
            <bbb id="e1-b"></bbb>
        </child>
    </element1>
    <element2 id="e2-1"/>
    <element3 id="e3-1"/>
    <element3 id="e3-2"/>
    <element3 id="e3-3"/>
</root>

This stylesheet does what I think you are trying to do - it processes each element3and processes all the ../element1/child/*nodes for each element3:

此样式表执行我认为您正在尝试执行的操作 - 它处理每个element3并处理../element1/child/*每个节点的所有节点element3

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

    <xsl:output indent="yes"/>
    <xsl:template match="root">
        <tests>
            <xsl:apply-templates select="element3"/>
        </tests>
    </xsl:template>

    <xsl:template match="element3">
        <xsl:apply-templates select="../element1/child/*">
            <xsl:with-param name="parent-pos" select="position() - 1"/>
            <xsl:with-param name="parent-id" select="@id"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="element1/child/*">
        <xsl:param name="parent-pos"/>
        <xsl:param name="parent-id"/>
        <xsl:variable name="current-pos" select="position()"/>

        <test parent-id="{$parent-id}" current-id="{@id}" parent-pos="{$parent-pos}" current-pos="{$current-pos}"/>

    </xsl:template>

</xsl:stylesheet>

The result is:

结果是:

<tests>
   <test parent-id="e3-1" current-id="e1-a" parent-pos="0" current-pos="1"/>
   <test parent-id="e3-1" current-id="e1-b" parent-pos="0" current-pos="2"/>
   <test parent-id="e3-2" current-id="e1-a" parent-pos="1" current-pos="1"/>
   <test parent-id="e3-2" current-id="e1-b" parent-pos="1" current-pos="2"/>
   <test parent-id="e3-3" current-id="e1-a" parent-pos="2" current-pos="1"/>
   <test parent-id="e3-3" current-id="e1-b" parent-pos="2" current-pos="2"/>
</tests>

Hope that helps

希望有帮助