与xsl:sort一起使用previous-sibling [英] using preceding-sibling with with xsl:sort

查看:118
本文介绍了与xsl:sort一起使用previous-sibling的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对记录的子集使用前级同级和后级同级.前面/后面带回原始xml顺序中的值的问题:

I'm trying to use preceding-sibling and following-sibling with a subset of records with a sort on them. The problem that the preceding / following brings back values from the original xml order:

<Salaries>
    <Salary>
        <Base>1000</Base>
        <CreatedDate xmlns:d7p1="http://schemas.datacontract.org/2004/07/System">
            <d7p1:DateTime>2016-01-09T14:38:54.8440764Z</d7p1:DateTime>
            <d7p1:OffsetMinutes>0</d7p1:OffsetMinutes>
        </CreatedDate>
    </Salary>
    <Salary>
        <Base>2000</Base>
        <CreatedDate xmlns:d7p1="http://schemas.datacontract.org/2004/07/System">
            <d7p1:DateTime>2015-01-09T14:38:54.8440764Z</d7p1:DateTime>
            <d7p1:OffsetMinutes>0</d7p1:OffsetMinutes>
        </CreatedDate>
    </Salary>
    <Salary>
        <Base>3000</Base>
        <CreatedDate xmlns:d7p1="http://schemas.datacontract.org/2004/07/System">
            <d7p1:DateTime>2017-01-09T14:38:54.8440764Z</d7p1:DateTime>
            <d7p1:OffsetMinutes>0</d7p1:OffsetMinutes>
        </CreatedDate>
    </Salary>
</Salaries>

当我在带有ac#函数的for-each(薪水/薪水)下使用排序时,将偏移分钟数添加到日期中并转换为长整数201701010000(例如,使在xslt中的操作更加容易).

When I use a sort under a for-each (Salaries/Salary) with a c# function to add offset minutes into a date and convert to a long number 201701010000 for example(to make manipulation in xslt easier).

<xsl:sort select="number(cs:Convertdatetolong(cs:AddOffsetMinutes(substring(p:CreatedDate/d5p1:DateTime,1,19),p:CreatedDate/d5p1:OffsetMinutes)))" order="ascending"/>

排序工作正常,我按以下顺序获取记录:

The sort works perfectly and I get the records out in the following order:

  • 2000
  • 1000
  • 3000

如果我使用previous-sibling/previous(和following),问题就来了.我希望第一个记录(2000)没有前面的记录,而最后一个记录(3000)没有后面的记录. 但是,当我使用前一个/后一个时,我从原始XML中获取了上一条记录和下一条记录:

The problem comes if I use preceding-sibling / preceding (and following). I would expect the first record (2000) to have no preceding record and the last record (3000) to have no following. However when I use the preceding / following I get the previous record and the next record from the original XML:

  • 2000(前-1000/后-3000)
  • 1000(2000年之前-/2000年之后)
  • 3000(之前-2000/之后-)

我希望能够与上一个记录(按排序顺序)和当前记录(按排序顺序)进行比较:

I would like to be able to compare against the previous record (in the sorted order) and the current record (in the sorted order):

  • 2000(前-后-1000)
  • 1000(2000年以前/3000以下)
  • 3000(前-1000/后-)

我已经尝试过在先兄弟和先在

I've tried preceding-sibling and preceding

<xsl:value-of select="preceding::p:Salary[1]/p:Base"/>
<xsl:value-of select="preceding-sibling::p:Salary[1]/p:Base"/>
<xsl:value-of select="preceding::p:Salary[position()=1]/p:Base"/>

(薪水在其他命名空间(p)中 真的有可能吗?还是我必须使用变量保存以前记录的数据以进行比较?

(the salary is in a different namespace (p) Is this actually possible or do I have to use variables to save the previous record's data to compare against?

任何想法都深表感谢.我正在使用xslt 1.0

Any ideas gratefully received. I'm using xslt 1.0

推荐答案

尽管XSLT/XPath经常提到节点序列",但实际上将其视为节点引用序列"更为准确-因为,例如,同一节点在序列中可以出现多次.对节点引用序列进行排序时,您不会以任何方式更改单个节点,而只需更改序列.这意味着这些节点仍然存在于它们原来的树中,与它们之前的位置完全相同,并且它们的父母,兄弟姐妹和后代与之前的位置完全一样.

Although XSLT/XPath often talks of a "sequence of nodes", it's actually more accurate to think of it as a "sequence of node references" - because, for example, the same node can appear more than once in the sequence. When you sort a sequence of node references, you don't change the individual nodes in any way, you only change the sequence. That means the nodes still exist in their original tree exactly where they were before, and their parents, siblings, and descendants are exactly as they were before.

您想要的不是节点的前后同级,而是按排序顺序在其前后的节点,这是完全不同的事情.

What you want is not the preceding and following siblings of the node, but the nodes that come before and after it in the sorted sequence, which is a quite different thing.

执行此操作的一种方法是构造一个包含原始节点副本的新树,例如,您会得到

One way to do this is to construct a new tree containing copies of the original nodes, which you get, for example, if you do

<xsl:variable name="x">
  <xsl:for-each ...>
    <xsl:sort ...>
      <xsl:copy-of select="."/>

然后,复制节点的兄弟关系将反映排序的顺序.还有一个小问题,在XSLT 1.0中,$ x是结果树片段,因此您必须使用exslt:node-set()函数将其转换为节点集.

The sibling relationships of the copied nodes will then reflect the sorted order. There's the minor problem that in XSLT 1.0, $x is a result tree fragment so you have to convert it to a node-set using the exslt:node-set() function.

实际上,在XSLT 1.0中,这可能是唯一的方法,因为XSLT 1.0数据模型仅具有节点集,而没有序列,这意味着除了文档以外,没有其他方法可以捕获和处理节点序列.命令. 2.0模型具有更大的灵活性和功能.如果可以的话,请升级-XSLT 1.0已有20年的历史了.

In fact in XSLT 1.0 that's probably the only way of doing it, because the XSLT 1.0 data model only has node sets, not sequences, which means there is no way of capturing and processing a sequence of nodes in anything other than document order. The 2.0 model has much more flexibility and power. Upgrade if you can - XSLT 1.0 is approaching 20 years old.

这篇关于与xsl:sort一起使用previous-sibling的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆