如何使用 XSL-FO(和 Apache FOP)计算从应用模板返回的元素 [英] How to count elements returned from applied template using XSL-FO (and Apache FOP)

查看:29
本文介绍了如何使用 XSL-FO(和 Apache FOP)计算从应用模板返回的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做一些类似于这个 但使用 XSL-FO 和 Apache FOP.

I would like to do something similar to this but using XSL-FO and Apache FOP.

我有这样的 xml 输入(与链接问题中的完全一样):

I have xml input like this (exactly like in the linked question):

<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),我将在其中显示以下文本:

I would like to create XSL file which will generate XSL-FO to generate PDF (using Apache FOP) in which I will display the following text:

Total Quantity: 3
Passed: 1
Failed: 2

这些数字是:

  • 总数量 - 唯一序列号的数量(在本例中为:1111、2222 和 3333),
  • 通过 - 通过的结果数量,但只计算每个唯一序列号的最新结果(最高Date)(在本例中仅为 3333 SerialNumberDate 99),
  • 失败 - 失败结果的数量,但只计算每个唯一序列号(在本例中为Date)的最新结果(最高Date)88 表示 1111,Date 40 表示 2222).
  • Total Quantity - number of unique serial numbers (in this case: 1111, 2222 and 3333),
  • Passed - number of passed results but counting only the latest result (the highest Date) per unique serial number (in this case only 3333 SerialNumber with Date 99),
  • Failed - number of failed results but counting only the latest result (the highest Date) per unique serial number (in this case Date 88 for 1111 and Date 40 for 2222).

换句话说,我只需要计算每个 SerialNumber 的最新 Date 的结果数.结果未排序.

In another words I need to count number of results only for the latest Date per SerialNumber. Results are not sorted.

我尝试了 michael.hor257k 建议的解决方案(当我只使用 xslt 在浏览器中生成 html 时有效):

I tried solution suggested by michael.hor257k (which works when I use just xslt to generate html in my browser):

<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 返回 未知格式对象{}输出";遇到错误.如何处理此错误并显示我的结果摘要?

But Apache FOP returns Unknown formatting object "{}output" encountered error. How to deal with this error and display my results summary?

这是我当前的 xsl 文件:

Here is my current xsl file:

<?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 转换产生以下结果:

So, assuming you want your XSL transformation to produce a result of:

<?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>

您可以使用以下样式表:

you can use the following stylesheet:

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>

这篇关于如何使用 XSL-FO(和 Apache FOP)计算从应用模板返回的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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