XML到XSL-FO的XSL样式表

时间:2018-08-18 13:58:21

标签: xml xslt xsl-fo apache-fop

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

文本

  • 表格

    图像<媒体参考mime-type =“ application / gif” source =“ foo.gif”>

    到目前为止,我已经设法转换了XML文件的文本部分。而且我可以处理仅包含具有固定列号的简单表的文件。当我尝试处理源文件中的文本和表格时,出现转换错误。 附带了(无效的)样式器my.xsl以及源文件。错误是

    org.apache.fop.fo.ValidationException:“ fo:table-body”缺少子元素。必需的内容模型:标记*(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 >

1 个答案:

答案 0 :(得分:2)

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

如果您使用的是行业标准XML,则XSL可能存在于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(添加省略的close 标记之后),然后使用Apache FOP将生成的FO格式化为PDF,它产生以下结果:

enter image description here

现在,您当然可以根据需要检查那些XSL,以查看您在XSL中做错了什么,但是正如您所看到的那样,这些XSL已经投入了很多工作。我总是会尽量避免“重新发明轮子”。

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

enter image description here