简体   繁体   English

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

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

The input xml has following hierarchy. 输入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>

I have a xsl template where part of it looks like 我有一个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>

Now even after applying sort function, the count function is following the order of 'd' in the input xml and not based on sorted ascending order of 'd' in the for-each statement. 现在,即使在应用了sort函数之后,count函数也遵循输入xml中“ d”的顺序,而不是基于for-each语句中“ d”的排序升序。 for-eg In loop 2 of element b ie b[position()=2] i am getting cnt = 3 though it should be 2. Please advice. for-eg在元素b的循环2中,即b [position()= 2],尽管应该为2,但我正在得到cnt = 3

The preceding:: axis only looks at nodes in document order - the order that they really are in your input. 上一条::轴仅按文档顺序查看节点-节点实际在输入中的顺序。 It doesn't take anything like the current sequence or the current sort order into account. 它不会像当前序列或当前排序顺序那样考虑任何东西。

If you really want to count how many <d> elements there are before the current in, in the sort order, then you can do that knowing that each element before it should have a lower value for the sort key than the current one: 如果您真的想按排序顺序计算当前元素之前有多少<d>元素,那么您可以知道排序元素之前的每个元素的值应比当前元素的值低,从而做到这一点:

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

But there already is a function in xslt that will give you the position of the current node in the sort order of the for-each loop, which is the position() function. 但是xslt中已经有一个函数,它将以for-each循环的排序顺序为您提供当前节点的position() ,即position()函数。 It starts to count at 1 so you need to subtract one if you want to know how many nodes are before the current one: 它开始计数为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>

This is from the xslt 1.1 specification, which describes it better than the xslt 1.0 specification, but it is also true in xslt 1.0: 这来自xslt 1.1规范,它比xslt 1.0规范更好地描述了它,但是在xslt 1.0中也是如此:

[The context position is the position of the context item within the sequence of items currently being processed. [上下文位置是上下文项在当前正在处理的项目序列中的位置。 It changes whenever the context item changes. 每当上下文项更改时,它也会更改。 When an instruction such as xsl:apply-templates or xsl:for-each is used to process a sequence of items, the first item in the sequence is processed with a context position of 1, the second item with a context position of 2, and so on.] The context position is returned by the XPath expression position() . 当使用诸如xsl:apply-templates或xsl:for-each之类的指令来处理项目序列时,该序列中的第一个项目的上下文位置为1,第二个项目的上下文位置为2,等等。]上下文位置由XPath表达式position()

From your further comment it looks like you want a number that represents the overall order of the current node in the two for loops, in the sort order of the for loops. 从您的进一步注释中,您似乎希望得到一个数字,该数字代表两个for循环中当前节点的总体顺序(以for循环的排序顺序)。

You can use my first approach: to count the nodes that are before this one in the sort order by comparing the values using '<'. 您可以使用我的第一种方法:通过使用'<'比较值来按排序顺序计算在此节点之前的节点。

Then your XSL becomes: 然后,您的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>

I think this is what you describe. 我认为这就是您所描述的。 If you still want something else, then I think your question is not very clear - given your sample input file, please describe exactly what result you are looking for in which order. 如果您仍然想要其他东西,那么我认为您的问题不是很清楚-考虑到您的示例输入文件,请准确描述您以什么顺序寻找的结果。

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

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