需要 XSLT 转换来计算从应用模板返回的元素
Need XSLT transform to count elements returned from applied template
我有一个与此非常相似的问题:Need XSLT transform to remove duplicate elements - sorted by an attribute。我从最佳答案中提取了解决方案并稍作修改。我必须计算状态,但只考虑最新的结果。
我的模板如下所示:
<xsl:template match='Results/Result' mode='countstatus'>
<xsl:param name='status' select='"Pass"'/>
<xsl:for-each select="key('sn-key', SerialNumber)">
<xsl:sort select='./Date' order='descending'/>
<xsl:if test='((position() = 1) and (./Status=$status))'>
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
我不想显示所有匹配结果,只想显示应用此模板后返回的项目数。
我的关键定义是 <xsl:key name='sn-key' match='Results/Result' use='SerialNumber'/>
我用 <xsl:apply-templates select='Results/Result[generate-id() = generate-id(key("sn-key", SerialNumber)[1])]' mode='countstatus'/>
.
调用这个模板
编辑
重新思考一下,我发现我的问题有点不清楚。这里有更多详细信息。
我的输入是这样的:
<Results>
<Result ID="0">
<SerialNumber>3333</SerialNumber>
<Status>Fail</Status>
<Date>21</Date>
</Result>
<Result ID="1">
<SerialNumber>1111</SerialNumber>
<Status>Fail</Status>
<Date>34</Date>
</Result>
<Result ID="2">
<SerialNumber>1111</SerialNumber>
<Status>Pass</Status>
<Date>67</Date>
</Result>
<Result ID="3">
<SerialNumber>2222</SerialNumber>
<Status>Fail</Status>
<Date>40</Date>
</Result>
<Result ID="4">
<SerialNumber>1111</SerialNumber>
<Status>Fail</Status>
<Date>55</Date>
</Result>
<Result ID="5">
<SerialNumber>1111</SerialNumber>
<Status>Fail</Status>
<Date>88</Date>
</Result>
<Result ID="6">
<SerialNumber>2222</SerialNumber>
<Status>Fail</Status>
<Date>22</Date>
</Result>
<Result ID="7">
<SerialNumber>1111</SerialNumber>
<Status>Fail</Status>
<Date>86</Date>
</Result>
<Result ID="8">
<SerialNumber>3333</SerialNumber>
<Status>Pass</Status>
<Date>99</Date>
</Result>
</Results>
我想数例如Fail
状态出现了多少次,但仅考虑 SerialNumber
的最新结果。我之前展示的模板显示了 SerialNumber
的所有最新结果(但状态 Pass
)。我只想显示数字。例如,在查找失败次数时,我想显示 2
而不是 [1111 Fail 88, 2222 Fail 40]
.
我的转型现在看起来像这样(但我还需要其他东西):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name='sn-key' match='Results/Result' use='SerialNumber' />
<xsl:template match="/">
<xsl:apply-templates select="Results/Result[generate-id()=generate-id(key('sn-key', SerialNumber)[1])]"/>
</xsl:template>
<xsl:template match="Results/Result">
<xsl:param name='status' select='"Fail"'/>
<xsl:for-each select="key('sn-key', SerialNumber)">
<xsl:sort select="./Date" order="descending"/>
<xsl:if test='((position() = 1) and (./Status=$status))'>
<xsl:value-of select="."/><br />
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
--- 根据澄清进行编辑 ---
I would like to count e.g. how many times the Fail status occurs, but considering only the latest results for SerialNumber.
我认为这可以转化为:
- 按序列号对
Result
进行分组;
- 计算最近
Result
有 Status
个“失败”的组
具体方法取决于 Result
是否在输入中按时间顺序列出 XML。
如果答案是肯定的,您可以简单地将 Muenchian 方法修改为 select the last(而不是通常的 first) Result
在每组中,添加另一个谓词以仅保留那些 Status
为“失败”的谓词并计算此组。这是一条单线:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="result-by-sn" match="Result" use="SerialNumber" />
<xsl:template match="/Results">
<output>
<xsl:value-of select="count(Result[count(. | key('result-by-sn', SerialNumber)[last()]) = 1][Status='Fail'])"/>
</output>
</xsl:template>
</xsl:stylesheet>
如果答案是否定的,那你只好实际进行分组排序过滤成一个变量,然后统计结果:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="result-by-sn" match="Result" use="SerialNumber" />
<xsl:template match="/Results">
<xsl:variable name="temp">
<xsl:for-each select="Result[count(. | key('result-by-sn', SerialNumber)[1]) = 1]">
<xsl:for-each select="key('result-by-sn', SerialNumber)">
<xsl:sort select="Date" order="descending"/>
<xsl:if test="position()=1 and Status='Fail'">x</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<output>
<xsl:value-of select="string-length($temp)"/>
</output>
</xsl:template>
</xsl:stylesheet>
我有一个与此非常相似的问题:Need XSLT transform to remove duplicate elements - sorted by an attribute。我从最佳答案中提取了解决方案并稍作修改。我必须计算状态,但只考虑最新的结果。
我的模板如下所示:
<xsl:template match='Results/Result' mode='countstatus'>
<xsl:param name='status' select='"Pass"'/>
<xsl:for-each select="key('sn-key', SerialNumber)">
<xsl:sort select='./Date' order='descending'/>
<xsl:if test='((position() = 1) and (./Status=$status))'>
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
我不想显示所有匹配结果,只想显示应用此模板后返回的项目数。
我的关键定义是 <xsl:key name='sn-key' match='Results/Result' use='SerialNumber'/>
我用 <xsl:apply-templates select='Results/Result[generate-id() = generate-id(key("sn-key", SerialNumber)[1])]' mode='countstatus'/>
.
编辑
重新思考一下,我发现我的问题有点不清楚。这里有更多详细信息。
我的输入是这样的:
<Results>
<Result ID="0">
<SerialNumber>3333</SerialNumber>
<Status>Fail</Status>
<Date>21</Date>
</Result>
<Result ID="1">
<SerialNumber>1111</SerialNumber>
<Status>Fail</Status>
<Date>34</Date>
</Result>
<Result ID="2">
<SerialNumber>1111</SerialNumber>
<Status>Pass</Status>
<Date>67</Date>
</Result>
<Result ID="3">
<SerialNumber>2222</SerialNumber>
<Status>Fail</Status>
<Date>40</Date>
</Result>
<Result ID="4">
<SerialNumber>1111</SerialNumber>
<Status>Fail</Status>
<Date>55</Date>
</Result>
<Result ID="5">
<SerialNumber>1111</SerialNumber>
<Status>Fail</Status>
<Date>88</Date>
</Result>
<Result ID="6">
<SerialNumber>2222</SerialNumber>
<Status>Fail</Status>
<Date>22</Date>
</Result>
<Result ID="7">
<SerialNumber>1111</SerialNumber>
<Status>Fail</Status>
<Date>86</Date>
</Result>
<Result ID="8">
<SerialNumber>3333</SerialNumber>
<Status>Pass</Status>
<Date>99</Date>
</Result>
</Results>
我想数例如Fail
状态出现了多少次,但仅考虑 SerialNumber
的最新结果。我之前展示的模板显示了 SerialNumber
的所有最新结果(但状态 Pass
)。我只想显示数字。例如,在查找失败次数时,我想显示 2
而不是 [1111 Fail 88, 2222 Fail 40]
.
我的转型现在看起来像这样(但我还需要其他东西):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name='sn-key' match='Results/Result' use='SerialNumber' />
<xsl:template match="/">
<xsl:apply-templates select="Results/Result[generate-id()=generate-id(key('sn-key', SerialNumber)[1])]"/>
</xsl:template>
<xsl:template match="Results/Result">
<xsl:param name='status' select='"Fail"'/>
<xsl:for-each select="key('sn-key', SerialNumber)">
<xsl:sort select="./Date" order="descending"/>
<xsl:if test='((position() = 1) and (./Status=$status))'>
<xsl:value-of select="."/><br />
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
--- 根据澄清进行编辑 ---
I would like to count e.g. how many times the Fail status occurs, but considering only the latest results for SerialNumber.
我认为这可以转化为:
- 按序列号对
Result
进行分组; - 计算最近
Result
有Status
个“失败”的组
具体方法取决于 Result
是否在输入中按时间顺序列出 XML。
如果答案是肯定的,您可以简单地将 Muenchian 方法修改为 select the last(而不是通常的 first) Result
在每组中,添加另一个谓词以仅保留那些 Status
为“失败”的谓词并计算此组。这是一条单线:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="result-by-sn" match="Result" use="SerialNumber" />
<xsl:template match="/Results">
<output>
<xsl:value-of select="count(Result[count(. | key('result-by-sn', SerialNumber)[last()]) = 1][Status='Fail'])"/>
</output>
</xsl:template>
</xsl:stylesheet>
如果答案是否定的,那你只好实际进行分组排序过滤成一个变量,然后统计结果:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="result-by-sn" match="Result" use="SerialNumber" />
<xsl:template match="/Results">
<xsl:variable name="temp">
<xsl:for-each select="Result[count(. | key('result-by-sn', SerialNumber)[1]) = 1]">
<xsl:for-each select="key('result-by-sn', SerialNumber)">
<xsl:sort select="Date" order="descending"/>
<xsl:if test="position()=1 and Status='Fail'">x</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<output>
<xsl:value-of select="string-length($temp)"/>
</output>
</xsl:template>
</xsl:stylesheet>