1

我一直在为 fop 0.95 的一些奇怪行为而苦苦挣扎(不知道我是否做错了什么,或者是否有解决方法)。

我有一个自动生成的 XML,如下所示:

<项目团队>
 <projectname>报告生成</projectname>
 <角色类型>
         <开发者/>
         <qa/>
         <文档/>
 </角色类型>
 <成员>
   <name>约翰</name>
   <dev>200</dev>
 </会员>
 <成员>
   <name>最大</name>
   <dev>60</dev>
 </会员>
 <成员>
   <name>亨利</name>
   <qa>80</qa>
 </会员>
 <成员>
   <name>彼得</name>
   <qa>40</qa>
 </会员>
</项目团队>

(注意:这是一个模拟示例,但我有一个非常相似的需求,我需要在作业结束时使用类似于 roleTypes 的几个列生成报告)

我的目标是以 pdf 格式显示上述数据,如下所示:

姓名 | 开发 | 问答 | 文档 |
--------------------------
约翰 | 100 | | |
最大 | 60 | | |
亨利 | | 80 | |
彼得 | | 40 | |

我使用 xsl:for-each 循环 RoleTypes/* 元素以定义表格列,然后动态构造 XPath 表达式(使用 exslt 的 dyn:evaluate)来获取与角色(dev、qa 和文档)。

如果我通过预处理器 (xsltproc) 运行它以生成 .fo,然后使用 fop 将此 .fo 转换为 pdf,我的 xsl 样式表将按预期工作。但是,当我直接使用 fop 时(即单步:fop -xml blah.xml -xsl blah.xsl -pdf out.pdf),我得到了奇怪的结果 - 只有第一列的数据(即 ' 的第一个子元素RoleTypes',在这个例子中 - 'dev')和其余的列是空白的。我也尝试过使用 fop 本身(-foout 选项)首先生成 .fo,然后使用 fop 生成 pdf,但得到了相同的结果,即数据仅显示在与 RoleTypes 的第一个子元素对应的列中元素。这是 fop 的错误吗(因为它似乎可以识别 dyn:evaluate,但没有完成完整的工作)?

我真的很想使用单步 fop,这样我就不需要在客户端上部署其他工具(如 xsltproc 等)。

这是我一直在使用的样式表的关键部分:

<xsl:stylesheet 版本="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:dyn="http://exslt.org/dynamic">

<xsl:template match="projectteam">
 ...
 <fo:table table-layout="fixed" width="100%">
  <fo:table-column column-width="3cm"/>
  <xsl:for-each select="RoleTypes/*">
   <fo:table-column column-width="1cm"/>
  </xsl:for-each>

  <fo:table-body>
  <xsl:for-each select="member">
   <xsl:variable name="Member" select="."/>
   <fo:table-row>
    <fo:table-cell>
     <fo:block> <xsl:value-of select="name"/></fo:block>
    </fo:table-cell>

    <xsl:for-each select="../RoleTypes/*">
     <xsl:variable name="roleName" select="concat('$Member/', name(.))"/>
     <fo:table-cell><fo:block>

     <!-- 这就是 fop 的问题所在;虽然同样的语句适用于 xsltproc?? -->

      <xsl:value-of select="dyn:evaluate($roleName)"/>
     </fo:block></fo:table-cell>
    </xsl:for-each>
   </fo:table-row>
  </xsl:for-each>
  </fo:table-body>
 </fo:table>
</xsl:模板>
</xsl:样式表>

谢谢

4

2 回答 2

2

这并不能解决在 FOP 中使用 dyn:evaluate 的一般问题,但是对于这个特定的模式和问题,不需要动态评估。您可以使用 name() 函数来匹配节点名称。如果将示例的内部循环替换为:

                    <xsl:for-each select="../RoleTypes/*">
                        <xsl:variable name="roleName" select="name(.)"/>
                        <fo:table-cell><fo:block>
                            <xsl:value-of select="$Member/*[name()=$roleName]"/>
                        </fo:block></fo:table-cell>
                    </xsl:for-each>

你会得到你想要的输出。

于 2009-10-24T15:16:04.050 回答
1

正如在http://markmail.org/message/np4t6fe4nsmr4vag中所指出的,这不是直接的 FOP 问题,而是在您的 Java 安装中处于活动状态的默认 XSLT 处理器的问题。XSLT 处理器可能需要显式替换,如下所述:http: //xml.apache.org/xalan-j/faq.html#faq-N100EF

当然,您也可以继续使用 xsltproc 生成 XSL-FO,然后将 FO 文件提供给 FOP。

于 2009-10-06T05:52:43.673 回答