我想知道如何修改XSL,以便从下面的XML中以相反的顺序显示最后5个节点。
<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type='text/xsl' href='ResultXSL.xsl'?>
<Automation>
<Run>
<client1>
<Date>25/02/2014</Date>
<TotalTests>23</TotalTests>
<Success>13</Success>
<Failures>10</Failures>
</client1>
<client2>
<Date>25/02/2014</Date>
<TotalTests>4</TotalTests>
<Success>0</Success>
<Failures>4</Failures>
</client2>
<client3>
<Date>25/02/2014</Date>
<TotalTests>9</TotalTests>
<Success>3</Success>
<Failures>6</Failures>
</client3>
</Run>
<Run>
<client1>
<Date>26/02/2014</Date>
<TotalTests>23</TotalTests>
<Success>13</Success>
<Failures>10</Failures>
</client1>
<client2>
<Date>25/02/2014</Date>
<TotalTests>4</TotalTests>
<Success>0</Success>
<Failures>4</Failures>
</client2>
<client3>
<Date>25/02/2014</Date>
<TotalTests>9</TotalTests>
<Success>3</Success>
<Failures>6</Failures>
</client3>
</Run>
<Run>
<client1>
<Date>27/02/2014</Date>
<TotalTests>23</TotalTests>
<Success>13</Success>
<Failures>10</Failures>
</client1>
<client2>
<Date>25/02/2014</Date>
<TotalTests>4</TotalTests>
<Success>0</Success>
<Failures>4</Failures>
</client2>
<client3>
<Date>25/02/2014</Date>
<TotalTests>9</TotalTests>
<Success>3</Success>
<Failures>6</Failures>
</client3>
</Run>
</Automation>
在下面的XSL中,我按正确的顺序从XML获取最后5个节点。我们如何修改它以按相反的顺序获取xml节点?
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:TESA="tesa.philips.com">
<xsl:template match="/">
<html>
<head>
<meta http-equiv="refresh" content="30" />
</head>
<body>
<hr/>
<p>
<table border="5" cellpadding="3" cellspacing="0" width="1200">
<tr>
<th style="font-weight:bold;background:#a6caf0;width:350px;height:80">Date</th>
<th style="font-weight:bold;background:#a6caf0;width:350px">Total Tests</th>
<th style="font-weight:bold;background:#a6caf0;width:350px">Passed</th>
<th style="font-weight:bold;background:#a6caf0;width:350px">Failure</th>
</tr>
<xsl:variable name="vvr_count" select="count(Automation/Run)"/>
<xsl:variable name="vvr_latest10" select="number($vvr_count) - 5"/>
<xsl:for-each select="Automation/Run">
<xsl:if test="$vvr_latest10 <= position()">
<tr>
<td class="cellTextLeft">
<xsl:value-of select="client1/Date"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client1/TotalTests"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client1/Success"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client1/Failures"/>
</td>
</tr>
<tr>
<td class="cellTextLeft">
<xsl:value-of select="client2/Date"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client2/TotalTests"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client2/Success"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client2/Failures"/>
</td>
</tr>
<tr>
<td class="cellTextLeft">
<xsl:value-of select="client3/Date"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client3/TotalTests"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client3/Success"/>
</td>
<td class="cellTextLeft">
<xsl:value-of select="client3/Failures"/>
</td>
</tr>
<tr style="background:Gray">
<td style="height:20"> - </td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</xsl:for-each>
</table>
</p>
</body>
</html>
答案 0 :(得分:1)
有很多方法可以解决这个问题。此方法旨在避免迭代可能是大量实例以查找最后一个5.在您的情况下,这可能不是一个因素,并且可能有更好的方法。
我使用的xml:
<root>
<e>a</e>
<e>b</e>
<e>c</e>
<e>d</e>
<e>e</e>
<e>f</e>
<e>g</e>
<e>h</e>
<e>i</e>
<e>j</e>
</root>
XSLT
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:TESA="tesa.philips.com">
<xsl:variable name="last" select="count(/root/e)"/> <!-- similar to what you did -->
<xsl:template match="/">
<xsl:call-template name="recurse"> <!-- begin recursion with last e node -->
<xsl:with-param name="which" select="$last"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="recurse"> <!-- each time through process a single e -->
<xsl:param name="which"/>
<xsl:apply-templates select="/root/e[$which]"/> <!-- get just the one we want -->
<xsl:if test="$which > ($last - 4)"> <!-- check to see if we have some left to do -->
<xsl:call-template name="recurse">
<xsl:with-param name="which" select="$which - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="e"> <!-- and here process it however you want. -->
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
您可以添加
<xsl:sort select="position()" order="descending" data-type="number"/>
作为for-each
的第一个孩子来反转处理顺序。如果这样做,您还需要更改“最后五个”测试,因为您现在想要处理逆序列表中的第一个五个节点。或者,将“最后五个”逻辑移动到for-each
选择表达式的谓词而不是使用if
可能更有意义:
<xsl:for-each select="(Automation/Run)[position() > last()-5]">
<xsl:sort select="position()" order="descending" data-type="number"/>
这种方法适用于XSLT 1.0和2.0(你已经标记了问题2.0,但你当前的样式表是version="1.0"
,所以你不清楚你真正需要的是什么。)
答案 2 :(得分:1)
这是一种输出任意项目列表的前N个的通用方法,具有可自由排序的附加好处。
对于我在position()
上排序的示例,当然,您可以将排序表达式更改为您需要的任何内容。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Automation">
<xsl:copy>
<xsl:apply-templates select="Run" mode="top-n">
<xsl:sort select="position()" order="descending" />
<xsl:with-param name="n" select="5"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="top-n">
<xsl:param name="n" />
<xsl:if test="position() <= $n">
<xsl:apply-templates select="." />
</xsl:if>
</xsl:template>
<xsl:template match="Run">
<xsl:copy-of select="." />
<!-- or whatever you want to do with a <Run> -->
</xsl:template>
</xsl:stylesheet>
只需将排序顺序切换为升序,即可分别获得前N个项目。
请注意模板模式。
答案 3 :(得分:0)
我愿意
<xsl:for-each select="subsequence(reverse(Automation/Run), 1, 5)">
...
</xsl:for-each>
虽然使用子序列提取最后5个可能会快一点,然后仅反转这五个。