XSLT fop-0.95:dyn 问题:评估

发布于 2024-08-06 23:05:52 字数 2792 浏览 4 评论 0原文

我一直在努力应对 fop 0.95 的一些奇怪行为(不知道我是否在做 出了问题,或者是否有解决方法)。

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

<projectteam>
 <projectname>Report Generation</projectname>
 <RoleTypes>
         <dev/>
         <qa/>
         <doc/>
 </RoleTypes>
 <member>
   <name>John</name>
   <dev>200</dev>
 </member>
 <member>
   <name>Max</name>
   <dev>60</dev>
 </member>
 <member>
   <name>Henry</name>
   <qa>80</qa>
 </member>
 <member>
   <name>Peter</name>
   <qa>40</qa>
 </member>
</projectteam>

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

我的目标是在 pdf 中显示上述数据,如下所示:

Name   | dev | qa  | doc |
--------------------------
John   | 100 |     |     |
Max    |  60 |     |     |
Henry  |     |  80 |     |
Peter  |     |  40 |     |

我使用 xsl:for-each 循环 RoleTypes/* 元素来定义表列,并且 然后动态构造XPath表达式(使用exslt的dyn:evaluate)得到 与角色(dev、qa 和 doc)相对应的单元格的数据。

如果我通过预处理器 (xsltproc) 运行我的 xsl 样式表,它会按预期工作 生成.fo,然后使用fop将此.fo转换为pdf。 但是,当我直接使用 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 version="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>

     <!-- This is where the problem is with fop; although the same statement works fine with 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:template>
</xsl:stylesheet>

谢谢

I've been struggling with some weird behavior of fop 0.95 (don't know if I'm doing
something wrong, or if there is a work around).

I have an auto generated XML as follows:

<projectteam>
 <projectname>Report Generation</projectname>
 <RoleTypes>
         <dev/>
         <qa/>
         <doc/>
 </RoleTypes>
 <member>
   <name>John</name>
   <dev>200</dev>
 </member>
 <member>
   <name>Max</name>
   <dev>60</dev>
 </member>
 <member>
   <name>Henry</name>
   <qa>80</qa>
 </member>
 <member>
   <name>Peter</name>
   <qa>40</qa>
 </member>
</projectteam>

(Note: This is a mocked up example, but I have a very similar need where I need
to generate reports at the end of a job with sevaral colums akin to roleTypes)

My goal is to display the above data in pdf as follows:

Name   | dev | qa  | doc |
--------------------------
John   | 100 |     |     |
Max    |  60 |     |     |
Henry  |     |  80 |     |
Peter  |     |  40 |     |

I used xsl:for-each to loop over RoleTypes/* elements to define table columns, and
then dynamically constructed XPath expression (using dyn:evaluate of exslt) to obtain
data for the cells that correspond to the roles (dev, qa, and doc).

My xsl stylesheet works as expected if I run it through a pre-processor (xsltproc)
to generate .fo, and then use fop to convert this .fo into a pdf.
But, when I use fop directly (i.e. single step: fop -xml blah.xml -xsl blah.xsl
-pdf out.pdf), I'm getting weird results - only the first column's data (i.e. the first
child element of 'RoleTypes', in this example - 'dev') and rest of the colums are blank.
I've also tried producing .fo first with fop itself (-foout option), and then using
fop to generate the pdf, but got the same result, i.e. data gets displayed only in the
column that corresponds to the first child element of RoleTypes element.
Is this a bug with fop (as it seems to recognize dyn:evaluate, but
doesn't do a complete job)?

I would really like to use the single step fop so that I wouldn't need
to deploy additional tools on the client box (like xsltproc etc).

Here's the critical segment of the stylesheet I've been using:

<xsl:stylesheet version="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>

     <!-- This is where the problem is with fop; although the same statement works fine with 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:template>
</xsl:stylesheet>

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

城歌 2024-08-13 23:05:53

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

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

As was noted at http://markmail.org/message/np4t6fe4nsmr4vag this is not directly a FOP problem but one with the default XSLT processor that is active in your Java installation. The XSLT processor may need to be replaced explicitely as described here:
http://xml.apache.org/xalan-j/faq.html#faq-N100EF

Of course, you can also just continue to use xsltproc for generating the XSL-FO and then feed FOP the FO file.

酒废 2024-08-13 23:05:52

这并没有回答在 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>

您将获得所需的输出。

This doesn't answer the general problem of using dyn:evaluate in FOP, but for this particular schema and problem, dynamic evaluation is not needed. You can use the name() function to match the node names. If you replace the inner loop of your example with:

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

You will get the output you wanted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文