【问题标题】:How to repeat same template in table-row using XSL-FO/Apache FOP如何使用 XSL-FO/Apache FOP 在表行中重复相同的模板
【发布时间】:2016-10-07 02:11:00
【问题描述】:

我正在尝试从我拥有的 XML 文件创建 PDF,到目前为止,它使用 XSL-FO/Apache FOP 运行良好。

XML 文件基本上包含条码信息:条码本身和条码类型(我会在某个时候添加条码图像)。

现在我希望看到的输出是这样的:

 -----------------------
| barcode1  | barcode2  |
| codetype1 | codetype2 |
 -----------------------
| barcode3  | barcode4  |
| codetype3 | codetype4 |
 -----------------------

等等。

我已经定义了以下 xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="fo">
  <xsl:template match="barcode-list">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="simpleA4" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
          <fo:region-body/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="simpleA4">
        <fo:flow flow-name="xsl-region-body">
          <fo:block font-size="10pt">
          <fo:table table-layout="fixed" width="100%" border-collapse="separate">    
            <fo:table-column column-width="45%"/>
            <fo:table-column column-width="45%"/>
            <fo:table-body>
              <xsl:apply-templates select="item"/>
            </fo:table-body>
          </fo:table>
          </fo:block>
        </fo:flow>
      </fo:page-sequence>
     </fo:root>
  </xsl:template>
  <xsl:template match="item">
    <fo:table-row>   
      <fo:table-cell>
        <fo:block wrap-option="wrap">
          <xsl:value-of select="name"/>
        </fo:block>
        <fo:block wrap-option="wrap">
          <xsl:value-of select="format"/>
        </fo:block>
      </fo:table-cell> 
    </fo:table-row>
  </xsl:template>
</xsl:stylesheet>

所以有两列,我想我可以将它指向“项目”模板来填充单元格。

现在我意识到“项目”模板包含一个&lt;table-row&gt; 标记,这会导致每个项目出现在自己的表格行中。所以我得到的是:

 -----------------------
| barcode1  |           |
| codetype1 |           |
 -----------------------
| barcode2  |           |
| codetype2 |           |
 -----------------------
| barcode3  |           |
| codetype3 |           |
 -----------------------
| barcode4  |           |
| codetype4 |           |
 -----------------------

我的问题是如何更改 xsl 以获得所需的输出,而不是将每个项目都放在自己的表格行中?

【问题讨论】:

  • XSLT 1.1 是一个没有任何进展的草案,被 XSLT 2.0 取代,现在/很快被 XSLT 3.0 取代。您使用的是哪种 XSLT 处理器?此外,exclude-result-prefixes="fo" 实际上什么也不做,因为输出中的每个元素都在 fo 命名空间中,这意味着 XSLT 处理器必须在结果中包含命名空间。最后,fo:root 上的xmlns:fo="http://www.w3.org/1999/XSL/Format"xsl:stylesheet 上的xmlns:fo="http://www.w3.org/1999/XSL/Format" 范围内,因此不是绝对必要的,也不影响输出。
  • @TonyGraham 如果我从文件中删除这两个元素中的任何一个,Apache FOP 会引发异常,抱怨未绑定元素和未知标签。
  • @TonyGraham 我必须对文档进行哪些更改才能使其符合 XSLT 2.0?
  • 异常似乎很奇怪。删除@exclude-result-prefixes 并从fo:root 中删除xmlns:fo 应该可以,但是由于更改会产生异常,因此不更改会更安全。根据您显示的内容,您可以将@version 值更改为2.0。 XSLT 2.0 规范的附录 J 中列出了一些极端情况,但大多数 XSLT 1.0 样式表在版本号更改后在 XSLT 2.0 处理器中都能正常工作。当然,您应该测试在更改版本号后输出不会发生变化。
  • @TonyGraham 感谢您的帮助。更改版本号工作得很好。顺便说一句:我得到的例外是:“元素“fo:table-cell”的前缀“fo”未绑定”

标签: java xml pdf xsl-fo apache-fop


【解决方案1】:

省略fo:table-row 并使用很少使用的starts-row (https://www.w3.org/TR/xsl11/#starts-row) 和/或ends-row (https://www.w3.org/TR/xsl11/#ends-row) 属性:

<xsl:template match="item">
  <fo:table-cell>
    <xsl:if test="position() mod 2 = 1">
      <xsl:attribute name="starts-row">true</xsl:attribute>
    </xsl:if>
    <fo:block wrap-option="wrap">
      <xsl:value-of select="name"/>
    </fo:block>
    <fo:block wrap-option="wrap">
      <xsl:value-of select="format"/>
    </fo:block>
  </fo:table-cell> 
</xsl:template>

【讨论】:

  • 这几乎可以完成这项工作。谢谢!
猜你喜欢
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 2020-04-06
  • 2018-06-22
  • 1970-01-01
  • 2023-02-22
  • 2017-06-02
  • 2013-01-20
相关资源
最近更新 更多