如何使用 XSL-FO(和 Apache FOP)计算从应用模板返回的元素
How to count elements returned from applied template using XSL-FO (and Apache FOP)
我想做类似于 但使用 XSL-FO 和 Apache FOP 的事情。
我有 xml 这样的输入(与链接问题中的完全一样):
<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>
我想创建 XSL 文件,它将生成 XSL-FO 以生成 PDF(使用 Apache FOP),我将在其中显示以下文本:
Total Quantity: 3
Passed: 1
Failed: 2
这些数字是:
- 总数量 - 唯一序列号的数量(在本例中为:1111、2222 和 3333),
- 已通过 - 通过结果的数量,但仅计算每个唯一序列号的最新结果(最高
Date
)(在本例中仅为 3333 SerialNumber
与 Date
99),
- 失败 - 失败结果的数量,但仅计算每个唯一序列号的最新结果(最高
Date
)(在本例中为 Date
88对于 1111 和 Date
40 对于 2222)。
换句话说,我只需要计算每个 SerialNumber
的最新 Date
结果的数量。结果未排序。
我尝试了 (当我只使用 xslt 在我的浏览器中生成 html 时有效):
<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>
但是 Apache FOP returns Unknown formatting object "{}output" encountered
错误。如何处理这个错误并显示我的结果摘要?
编辑:
这是我当前的 xsl 文件:
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!-- KEY FOR FINDING UUT RESULTS -->
<xsl:key name="result-by-sn" match="Results/Result" use="SerialNumber"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="my_page" margin="0.5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my_page">
<fo:flow flow-name="xsl-region-body">
<fo:block>Total Quantity: <xsl:value-of select="count(Results/Result[generate-id() = generate-id(key('result-by-sn', SerialNumber)[1])])"/></fo:block>
<fo:block>Passed: <!--<xsl:apply-templates select="Results" mode="count"><xsl:with-param name="status" select="'Pass'"/></xsl:apply-templates>--></fo:block>
<fo:block>Failed: <!--<xsl:apply-templates select="Results" mode="count"><xsl:with-param name="status" select="'Fail'"/></xsl:apply-templates>--></fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<!-- TEMPLATE TO COUNT RESULTS -->
<!--<xsl:template match="Results" mode="count">
<xsl:param name="status" select="'Pass'"/>
<xsl:variable name="temp">
<xsl:for-each select="Result[generate-id()=generate-id(key('result-by-sn', SerialNumber)[1])]">
<xsl:for-each select="key('result-by-sn', SerialNumber)">
<xsl:sort select="Date" order="descending"/>
<xsl:if test="position() = 1 and Status = $status">x</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<output>
<xsl:value-of select="string-length($temp)"/>
</output>
</xsl:template>-->
</xsl:stylesheet>
因此,假设您希望 XSL 转换产生以下结果:
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="my_page" margin="0.5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my_page">
<fo:flow flow-name="xsl-region-body">
<fo:block>Total Quantity: 3</fo:block>
<fo:block>Passed: 1</fo:block>
<fo:block>Failed: 2</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
您可以使用以下样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<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">
<!-- determine counts -->
<xsl:variable name="distinct-results" select="Result[count(. | key('result-by-sn', SerialNumber)[1]) = 1]" />
<xsl:variable name="count-distinct" select="count($distinct-results)" />
<xsl:variable name="fails">
<xsl:for-each select="$distinct-results">
<xsl:for-each select="key('result-by-sn', SerialNumber)">
<xsl:sort select="Date" order="descending"/>
<xsl:if test="position()=1 and Status='Fail'">F</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="count-fails" select="string-length($fails)" />
<!-- output -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="my_page" margin="0.5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my_page">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<xsl:text>Total Quantity: </xsl:text>
<xsl:value-of select="$count-distinct"/>
</fo:block>
<fo:block>
<xsl:text>Passed: </xsl:text>
<xsl:value-of select="$count-distinct - $count-fails"/>
</fo:block>
<fo:block>
<xsl:text>Failed: </xsl:text>
<xsl:value-of select="$count-fails"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
我想做类似于
我有 xml 这样的输入(与链接问题中的完全一样):
<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>
我想创建 XSL 文件,它将生成 XSL-FO 以生成 PDF(使用 Apache FOP),我将在其中显示以下文本:
Total Quantity: 3
Passed: 1
Failed: 2
这些数字是:
- 总数量 - 唯一序列号的数量(在本例中为:1111、2222 和 3333),
- 已通过 - 通过结果的数量,但仅计算每个唯一序列号的最新结果(最高
Date
)(在本例中仅为 3333SerialNumber
与Date
99), - 失败 - 失败结果的数量,但仅计算每个唯一序列号的最新结果(最高
Date
)(在本例中为Date
88对于 1111 和Date
40 对于 2222)。
换句话说,我只需要计算每个 SerialNumber
的最新 Date
结果的数量。结果未排序。
我尝试了
<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>
但是 Apache FOP returns Unknown formatting object "{}output" encountered
错误。如何处理这个错误并显示我的结果摘要?
编辑:
这是我当前的 xsl 文件:
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!-- KEY FOR FINDING UUT RESULTS -->
<xsl:key name="result-by-sn" match="Results/Result" use="SerialNumber"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="my_page" margin="0.5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my_page">
<fo:flow flow-name="xsl-region-body">
<fo:block>Total Quantity: <xsl:value-of select="count(Results/Result[generate-id() = generate-id(key('result-by-sn', SerialNumber)[1])])"/></fo:block>
<fo:block>Passed: <!--<xsl:apply-templates select="Results" mode="count"><xsl:with-param name="status" select="'Pass'"/></xsl:apply-templates>--></fo:block>
<fo:block>Failed: <!--<xsl:apply-templates select="Results" mode="count"><xsl:with-param name="status" select="'Fail'"/></xsl:apply-templates>--></fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<!-- TEMPLATE TO COUNT RESULTS -->
<!--<xsl:template match="Results" mode="count">
<xsl:param name="status" select="'Pass'"/>
<xsl:variable name="temp">
<xsl:for-each select="Result[generate-id()=generate-id(key('result-by-sn', SerialNumber)[1])]">
<xsl:for-each select="key('result-by-sn', SerialNumber)">
<xsl:sort select="Date" order="descending"/>
<xsl:if test="position() = 1 and Status = $status">x</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<output>
<xsl:value-of select="string-length($temp)"/>
</output>
</xsl:template>-->
</xsl:stylesheet>
因此,假设您希望 XSL 转换产生以下结果:
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="my_page" margin="0.5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my_page">
<fo:flow flow-name="xsl-region-body">
<fo:block>Total Quantity: 3</fo:block>
<fo:block>Passed: 1</fo:block>
<fo:block>Failed: 2</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
您可以使用以下样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<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">
<!-- determine counts -->
<xsl:variable name="distinct-results" select="Result[count(. | key('result-by-sn', SerialNumber)[1]) = 1]" />
<xsl:variable name="count-distinct" select="count($distinct-results)" />
<xsl:variable name="fails">
<xsl:for-each select="$distinct-results">
<xsl:for-each select="key('result-by-sn', SerialNumber)">
<xsl:sort select="Date" order="descending"/>
<xsl:if test="position()=1 and Status='Fail'">F</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="count-fails" select="string-length($fails)" />
<!-- output -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="my_page" margin="0.5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my_page">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<xsl:text>Total Quantity: </xsl:text>
<xsl:value-of select="$count-distinct"/>
</fo:block>
<fo:block>
<xsl:text>Passed: </xsl:text>
<xsl:value-of select="$count-distinct - $count-fails"/>
</fo:block>
<fo:block>
<xsl:text>Failed: </xsl:text>
<xsl:value-of select="$count-fails"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>