Sorting 将前面的同级与xsl:sort一起使用
我正在尝试使用前面的同级和后面的同级,并对记录子集进行排序。前面/下面的代码从原始xml顺序返回值的问题:Sorting 将前面的同级与xsl:sort一起使用,sorting,xslt,Sorting,Xslt,我正在尝试使用前面的同级和后面的同级,并对记录子集进行排序。前面/下面的代码从原始xml顺序返回值的问题: <Salaries> <Salary> <Base>1000</Base> <CreatedDate xmlns:d7p1="http://schemas.datacontract.org/2004/07/System"> <d7p1:DateTime>2
<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>
1000
2016-01-09T14:38:54.8440764Z
0
2000
2015-01-09T14:38:54.8440764Z
0
3000
2017-01-09T14:38:54.8440764Z
0
例如,当我使用a下的sort for each(salarys/Salary)和c#函数将偏移分钟数添加到日期中,并转换为一个长数字201701010000(以使xslt中的操作更容易)
排序工作正常,我按以下顺序取出记录:
- 2000年
- 一千
- 三千
- 2000年(前-1000/后-3000)
- 1000(2000年之前/之后)
- 3000(2000年之前/2000年之后)
- 2000年(之前/之后-1000年)
- 1000(2000年之前/3000年之后)
- 3000(前1000/后1000)
<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)
这实际上是可能的,还是我必须使用变量来保存前一条记录的数据以进行比较
我正在使用xslt 1.0,前面的同级轴按文档顺序获取上下文节点的前面同级
要在排序后引用节点前面的同级,首先需要将排序后的节点存储在变量中,并且在XSLT 1.0中,将变量转换为节点集。尽管XSLT/XPath经常提到“节点序列”,但实际上将其视为“节点引用序列”更为准确-因为,例如,同一个节点可以在序列中出现多次。对节点引用序列进行排序时,不会以任何方式更改单个节点,只会更改序列。这意味着节点仍然存在于其原始树中,与它们之前的位置完全相同,并且它们的父节点、同级节点和子节点都是完全相同的和以前一样,我很高兴 您需要的不是节点的前后兄弟节点,而是排序序列中位于它之前和之后的节点,这是一件完全不同的事情 实现这一点的一种方法是构造一个包含原始节点副本的新树,例如,如果您这样做,就会得到原始节点的副本
<xsl:variable name="x">
<xsl:for-each ...>
<xsl:sort ...>
<xsl:copy-of select="."/>
然后,复制节点的同级关系将反映排序顺序。有一个小问题是,在XSLT 1.0中,$x是一个结果树片段,因此必须使用exslt:node-set()函数将其转换为节点集
事实上,在XSLT 1.0中,这可能是实现这一点的唯一方法,因为XSLT 1.0数据模型只有节点集,而没有序列,这意味着除了文档顺序之外,无法捕获和处理节点序列。2.0模型具有更大的灵活性和功能。如果可以的话,请升级—XSLT 1.0即将迎来20年rs old.感谢Michael的回答。出于完整性考虑,发布在此处。由于xml中使用了空格,因此非常复杂:
<!-- Puts the whole of the Salary Node into a variable-->
<xsl:variable name="SALARY" >
<xsl:copy-of select="p:Salaries" />
</xsl:variable>
<!-- Puts the the required key data into a node-set with the correct sort applied-->
<xsl:variable name="SAL">
<xsl:for-each select="msxsl:node-set($SALARY)//p:Salary">
<xsl:sort select="number(cs:Convertdatetolong(cs:AddOffsetMinutes(substring(p:CreatedDate/d5p1:DateTime,1,19),p:CreatedDate/d5p1:OffsetMinutes)))" order="ascending"/>
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:variable>
<!-- Quick Output-->
<xsl:for-each select="msxsl:node-set($SAL)//p:Salary">
<xsl:text>Sa:</xsl:text>
<xsl:value-of select="position()" />
<xsl:text>Preceding:</xsl:text>
<xsl:value-of select="preceding-sibling::p:Salary[1]/p:Base"/>
<xsl:value-of select="$newline" />
<xsl:text>Current:</xsl:text>
<xsl:value-of select="p:Base"/>
<xsl:value-of select="$newline" />
<xsl:text>Following:</xsl:text>
<xsl:value-of select="following-sibling::p:Salary[1]/p:Base"/>
<xsl:value-of select="$newline"/>
</xsl:for-each>
Sa:
先前的:
当前:
以下:
谢谢。我已经成功地将值和日期按我希望的顺序放入一个节点集中。我正在努力将它们循环成一个for each:似乎不起作用啊,我必须使用相同的名称空间。doh.msxsl:node set($SAL)//p:Salary
<!-- Puts the whole of the Salary Node into a variable-->
<xsl:variable name="SALARY" >
<xsl:copy-of select="p:Salaries" />
</xsl:variable>
<!-- Puts the the required key data into a node-set with the correct sort applied-->
<xsl:variable name="SAL">
<xsl:for-each select="msxsl:node-set($SALARY)//p:Salary">
<xsl:sort select="number(cs:Convertdatetolong(cs:AddOffsetMinutes(substring(p:CreatedDate/d5p1:DateTime,1,19),p:CreatedDate/d5p1:OffsetMinutes)))" order="ascending"/>
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:variable>
<!-- Quick Output-->
<xsl:for-each select="msxsl:node-set($SAL)//p:Salary">
<xsl:text>Sa:</xsl:text>
<xsl:value-of select="position()" />
<xsl:text>Preceding:</xsl:text>
<xsl:value-of select="preceding-sibling::p:Salary[1]/p:Base"/>
<xsl:value-of select="$newline" />
<xsl:text>Current:</xsl:text>
<xsl:value-of select="p:Base"/>
<xsl:value-of select="$newline" />
<xsl:text>Following:</xsl:text>
<xsl:value-of select="following-sibling::p:Salary[1]/p:Base"/>
<xsl:value-of select="$newline"/>
</xsl:for-each>