繁体   English   中英

根据xslt 1.0中for-each循环的sort函数对节点进行计数

[英]Count nodes based on the sort function of for-each loop in xslt 1.0

输入xml具有以下层次结构。

<a>  
 <b>
  <b1>3</b1> 
  <c> 
    <d>
    <d1>13</d1>
    <d2>text1</d2> 
    </d>
    <d>
    <d1>14</d1>
    <d2>text2</d2>
    </d>   
    <d>
    <d1>12</d1>
    <d2>text3</d2> 
    </d>
  </c>  
 </b>  
 <b>
  <b1>2</b1> 
  <c>  
    <d> 
    <d1>11</d1>
    <d2>text5</d2>
    </d>
    <d>
    <d1>10</d1>
    <d2>text4</d2>
    </d>
  </c>  
 </b> 
  ---- and so on.
</a>

我有一个xsl模板,其中的一部分看起来像

    <xsl:for-each select="a/b">
    <xsl:sort select="b1" data-type="number"/>
    ----- other mapping---
     <xsl:for-each select="c/d">
     <xsl:sort select="d1" data-type="number"/>
       <xsl:variable name="cnt">
       <xsl:value-of select="count(preceding::../../c/d)"/>
      </xsl:variable>
     ------ other mapping------
     </xsl:for-each>
    </xsl:for-each>

现在,即使在应用了sort函数之后,count函数也遵循输入xml中“ d”的顺序,而不是基于for-each语句中“ d”的排序升序。 for-eg在元素b的循环2中,即b [position()= 2],尽管应该为2,但我正在得到cnt = 3

上一条::轴仅按文档顺序查看节点-节点实际在输入中的顺序。 它不会像当前序列或当前排序顺序那样考虑任何东西。

如果您真的想按排序顺序计算当前元素之前有多少<d>元素,那么您可以知道排序元素之前的每个元素的值应比当前元素的值低,从而做到这一点:

<xsl:variable name="d1" select="number(d1)" />
<xsl:value-of select="count(../d[number(d1) &lt; $d1])" />

但是xslt中已经有一个函数,它将以for-each循环的排序顺序为您提供当前节点的position() ,即position()函数。 它开始计数为1,因此如果您想知道当前节点之前有多少个节点,则需要减去一个:

<xsl:for-each select="a/b">
    <xsl:sort select="b1" data-type="number" />
    ----- other mapping---
    <xsl:for-each select="c/d">
        <xsl:sort select="d1" data-type="number" />
        <xsl:variable name="cnt">
            <xsl:value-of select="position() - 1" />
        </xsl:variable>
        ------ other mapping------
    </xsl:for-each>
</xsl:for-each>

这来自xslt 1.1规范,它比xslt 1.0规范更好地描述了它,但是在xslt 1.0中也是如此:

[上下文位置是上下文项在当前正在处理的项目序列中的位置。 每当上下文项更改时,它也会更改。 当使用诸如xsl:apply-templates或xsl:for-each之类的指令来处理项目序列时,该序列中的第一个项目的上下文位置为1,第二个项目的上下文位置为2,等等。]上下文位置由XPath表达式position()

从您的进一步注释中,您似乎希望得到一个数字,该数字代表两个for循环中当前节点的总体顺序(以for循环的排序顺序)。

您可以使用我的第一种方法:通过使用'<'比较值来按排序顺序计算在此节点之前的节点。

然后,您的XSL变为:

<xsl:for-each select="a/b">
    <xsl:sort select="b1" data-type="number" />
    ----- other mapping---
    <xsl:for-each select="c/d">
        <xsl:sort select="d1" data-type="number" />
        <xsl:variable name="me" select="." />
        <xsl:variable name="cnt">
            <xsl:value-of select="count(../d[number(d1) &lt; number($me/d1)]) + count(../../../b/c/d[number(../../b1) &lt; number($me/../../b1)])" />
        </xsl:variable>
        ------ other mapping------
    </xsl:for-each>
</xsl:for-each>

我认为这就是您所描述的。 如果您仍然想要其他东西,那么我认为您的问题不是很清楚-考虑到您的示例输入文件,请准确描述您以什么顺序寻找的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM