【问题标题】:XSL style sheet for XML to XSL-FOXML 到 XSL-FO 的 XSL 样式表
【发布时间】:2018-08-18 13:58:21
【问题描述】:

我需要将 XML 文件转换为 PDF,通过 XSL-FO 来完成。 源 XML 文件具有其结构和字典 (NITF),不应更改。我必须为这些文件创建特定的 XSL 样式器。在整个 XML 元素中,我只需要几个:

文字

  • 表格

    图像

    到目前为止,我已经成功地转换了 XML 文件的文本部分。而且我可以处理只包含一个具有固定列号的简单表的文件。当我尝试同时处理源文件中的文本和表格时,出现转换错误。 附加了(坏工作)样式器 my.xsl 以及源文件。这些错误有点

    org.apache.fop.fo.ValidationException:“fo:table-body”缺少子元素。所需内容模型:marker* (table-row+|table-cell+)

    XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE nitf SYSTEM "nitf.dtd">
    <nitf>
    <head>
        <title type="main">Sub-title 1</title>
        <meta name="filetype" content="content"/>
        <docdata><document-id id-string="123456" /></docdata>
    </head>
    <body>
        <body.head>
            <hedline><hl1>Sub-title 1</hl1></hedline>
        </body.head>
        <body.content>
            <ul>
                <li>Some long text 1</li><li>Some long text 2</li>
            </ul>
            <table  id="0001.csv">
                <tbody>
                    <tr>
                        <td colspan="4" class="tbh">Table tilte 1</td>
                    </tr>
                    <tr>
                        <td colspan="1" class="tbc">&#160;</td>
                        <td colspan="1" class="tbc-r">Col title 1</td>
                        <td colspan="1" class="tbc-r">Col title 2</td>
                        <td colspan="1" class="tbc-r">Col title 3</td>
                    </tr>
                    <tr>
                        <td colspan="1" class="tbd">Row title 1</td>
                        <td colspan="1" class="tbd-r">cell text 1</td>
                        <td colspan="1" class="tbd-r">cell text 2</td>
                        <td colspan="1" class="tbd-r">cell text 3</td>
                    </tr>
                    <tr>
                        <td colspan="1" class="tbd">Row title 2</td>
                        <td colspan="1" class="tbd-r">cell text 4</td>
                        <td colspan="1" class="tbd-r">cell text 5</td>
                        <td colspan="1" class="tbd-r">cell text 6</td>
                    </tr>
                    <tr>
                        <td colspan="4" class="footnote">Some footnote</td>
                    </tr>
                    <tr>
                        <td colspan="4" class="source">One more footnote</td>
                    </tr>
                </tbody>
            </table>
            <p class="text">Just a short text</p>
            <ul>
                <li>Some long text 3</li><li>Some long text 4</li>
            </ul>
        </body.content>
    </body>

    XSL:

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:stylesheet version="1.0" xmlns:fo="http://www.w3.org/1999/XSL/Format" 
                                  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" indent="yes"/>
    
    <xsl:template match="nitf">
        <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
    
            <fo:layout-master-set>
                <fo:simple-page-master page-height="297mm" page-width="210mm"
                    margin="5mm 25mm 5mm 25mm" master-name="simpleA4">
                <fo:region-body margin="20mm 0mm 20mm 0mm"/>
                </fo:simple-page-master>
            </fo:layout-master-set>
            <!-- NOTE: text part is OK! -->
            <fo:page-sequence master-reference="simpleA4">
                <fo:flow flow-name="xsl-region-body" >
                    <fo:block>
                        <xsl:apply-templates select="head"/>
                        <!--xsl:apply-templates select="body"/ If it's uncommented, the table is not seen-->
                    </fo:block>
                    <fo:block>
                        <fo:table table-layout="fixed" border-style="solid">
                                <xsl:apply-templates select="tr" mode="theader"/>
                                <xsl:apply-templates select="tr" mode="tbody"/> 
                            <fo:table-body>
                                <xsl:apply-templates select="body/table/tbody/tr"/>
                            </fo:table-body>
                        </fo:table>
                    </fo:block>
                </fo:flow>            
            </fo:page-sequence>
        </fo:root>
    </xsl:template>
    
      <xsl:template match="tr">
           <fo:table-row>
          <xsl:apply-templates select="td"/>
        </fo:table-row>
      </xsl:template>
      
      <xsl:template match="td">
        <fo:table-cell border-style="solid">
          <fo:block><xsl:value-of select="."/></fo:block>
        </fo:table-cell>
      </xsl:template>
    
    <!-- text -->
    <xsl:template match="head">
        <fo:inline font-weight="bold">
            <xsl:apply-templates/>
        </fo:inline>
    </xsl:template>
    
    <xsl:template match="body.head">
        <fo:inline font-weight="bold">
            <xsl:apply-templates/>
        </fo:inline>
    </xsl:template>
    
    <xsl:template match="body.content">
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="p">
        <fo:block>
            <xsl:apply-templates/>
        </fo:block>
    </xsl:template>
    <xsl:template match="b">
        <fo:inline font-weight="bold">
            <xsl:apply-templates/>
        </fo:inline>
    </xsl:template>
    
    </xsl:stylesheet >

    【问题讨论】:

    • 您的 XSL 有很多问题。没有具有“theader”或“tbody”模式的模板,因此它们什么都不做。您在表体内的匹配项是“body/table/tbody/tr”,它在您的 XML 中也不存在(至少会缺少“body.content”。它还会将许多表合并为一个。真正的问题这就是为什么要尝试编写已经存在的内容。请参阅下面的答案。

标签: xml xslt xsl-fo apache-fop


【解决方案1】:

Google 是您的朋友。我搜索了 NITF XSL FO,发现了这个https://github.com/ydirson/serna-free/tree/master/serna/dist/plugins/nitf/nitf-xsl-serna

如果您使用的是行业标准 XML,则可能存在用于 HTML 的 XSL,并且很多用于 XSL FO。

我从 Github 克隆并下载了该项目。 XSL 在那里并引用了其他一些。你只需要“dist”目录下,但有很多很多东西甚至在你不需要的。实际上,如果您检查根“nitf.xsl”,您会看到:

<xsl:import href="../../../xml/stylesheets/xslbricks/fo/fonts.xsl"/>
<xsl:import href="../../../xml/stylesheets/xslbricks/fo/common.xsl"/>
<xsl:import href="../../../xml/stylesheets/xslbricks/fo/layoutsetup.xsl"/>
<xsl:import href="../../../xml/stylesheets/xslbricks/fo/default-elements.xsl"/>
<xsl:import href="../../../xml/stylesheets/xslbricks/fo/page-sizes.xsl"/>
<xsl:import href="../../../xml/stylesheets/xslbricks/fo/xhtml-tables.xsl"/>

<xsl:include href="nitf-param.xsl"/>
<xsl:include href="nitf-common.xsl"/>
<xsl:include href="nitf-struct.xsl"/>
<xsl:include href="nitf-meta.xsl"/>
<xsl:include href="nitf-blocks.xsl"/>
<xsl:include href="nitf-inlines.xsl"/>
<xsl:include href="nitf-lists.xsl"/>
<xsl:include href="nitf-images.xsl"/>
<xsl:include href="nitf-tables.xsl"/>

那些导入/包含的文件将代表所有 XSL(除非其中一些还引用了其他文件,否则我没有检查)。

在上面运行您的 XML(在添加您省略的关闭 标记之后)并使用 Apache FOP 将生成的 FO 格式化为 PDF,它会产生以下结果:

现在,如果您愿意,当然可以检查这些 XSL 以观察您在 XSL 中做错了什么,但正如您所见,已经在这些 XSL 中投入了大量工作。我总是会尽量避免“重新发明轮子”。

要重新组织所有这些,您可以只隔离所需的 XSL,编辑主“nitf.xsl”以在一个目录中引用它们(如果您愿意)。我这样做了,它仍然可以正常工作(所以我没有检查的 XSL 都没有参考其他的),我的目录现在只有以下内容,我已经删除了其他所有内容:

【讨论】:

  • 这正是我所需要的!非常感谢你,凯文!问题是我有一些 nitf.xsl 并且无法处理我的文件。我应该花一些时间来搜索 - 但我决定编写自己的样式表。正如我现在所看到的,完全错误。
  • 凯文,我可以再问一点吗?您是否更改了我的 XML 中的某些内容(除了错过的最后一行)以获得成功的转换?我已经克隆了 serna,使用了它的 nitf.xsl 并得到了很多错误,例如“不存在名为 xhtml-tbody 的属性集(都是关于“xhtml”)
  • 以上是 oXygen 的结果。当我尝试 Apache FOP 时,它抛出了 TransformerConfigurationException: ERROR: '.../xhtml-tables.xsl: line 18: Error parsing XPath expression 'caption[not(self::processing-instruction('se:choice')) ]'。'致命错误:'.../nitf-tables.xsl:第 28 行:缺少必需的属性'test'。'
  • 您使用的是什么成本转换。我会使用撒克逊 6
  • 也许您正在为 html 运行 xslt 而不是为 FO 运行 xslt。检查它,看看它是否适用于 FO。
猜你喜欢
  • 2015-12-22
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 2012-11-07
  • 2015-06-14
  • 2012-04-03
相关资源
最近更新 更多