与 xsl:sort 一起使用前置同级 [英] using preceding-sibling with with xsl:sort

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

问题描述

我正在尝试使用前同级和后同级对记录的子集进行排序.前面/后面从原来的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 (Salaries/Salary) 下的排序将偏移分钟添加到日期中并例如转换为长数字 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(和后续),就会出现问题.我希望第一条记录 (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)
  • 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/后 - )

我试过previous-sibling 和previous

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 一起使用前置同级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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