java - xslt 函数 format-dateTime 在转换为 PDF 时不起作用

标签 java xml xslt-2.0 saxon apache-fop

我对 XSLT 和使用样式表非常陌生,所以也许我遗漏了一些明显的东西,但我在我的 xsl 中调用了 format-dateTime 函数,如下所示

                                <xsl:value-of
                                    select="format-dateTime(header/requestDetail/startDate,'[D01]/[M01]/[Y] [H01]:[m01]:[s01]','en',(),())" />

但这会返回以下错误消息

SystemId Unknown; Line #215; Column #118; Could not find function: format-dateTime
SystemId Unknown; Line #215; Column #118; A location path was expected, but the following token was encountered:  )
SystemId Unknown; Line #215; Column #118; A location path was expected, but the following token was encountered:  )
SystemId Unknown; Line #215; Column #118; function token not found.
(Location of error unknown)java.lang.NullPointerException
Exception in thread "main" java.lang.NullPointerException

有人能告诉我为什么会这样吗,因为据我所知,format-dateTime 是 XSLT 2.0 的内置函数。我的 Maven 依赖项中也有最新版本的 SAXON。

这是完整的xsl文件

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
    <xsl:output encoding="UTF-8" indent="yes" method="xml"
        standalone="no" omit-xml-declaration="no" />
    <xsl:template match="users-data">
        <fo:root language="EN">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="A4-portrail"
                    page-height="297mm" page-width="210mm" margin-top="5mm"
                    margin-bottom="5mm" margin-left="5mm" margin-right="5mm">
                    <fo:region-body margin-top="25mm" margin-bottom="20mm" />
                    <fo:region-before region-name="xsl-region-before"
                        extent="25mm" display-align="before" precedence="true" />
                </fo:simple-page-master>
            </fo:layout-master-set>
            <fo:page-sequence master-reference="A4-portrail">
                <fo:static-content flow-name="xsl-region-before">
                    <fo:table table-layout="fixed" width="100%" font-size="10pt"
                        border-color="black" border-width="0.4mm" border-style="solid">
                        <fo:table-column column-width="proportional-column-width(20)" />
                        <fo:table-column column-width="proportional-column-width(45)" />
                        <fo:table-column column-width="proportional-column-width(20)" />
                        <fo:table-body>
                            <fo:table-row>
                                <fo:table-cell text-align="left" display-align="center"
                                    padding-left="2mm">
                                    <fo:block>
                                        Bill Id:
                                        <xsl:value-of select="header-section/data-type/@id" />
                                        , Date:
                                        <xsl:value-of select="header-section/process-date" />
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="center" display-align="center">
                                    <fo:block font-size="150%">
                                        <fo:basic-link external-destination="http://www.example.com">XXX COMPANY
                                        </fo:basic-link>
                                    </fo:block>
                                    <fo:block space-before="3mm" />
                                </fo:table-cell>
                                <fo:table-cell text-align="right" display-align="center"
                                    padding-right="2mm">
                                    <fo:block>
                                        <xsl:value-of select="data-type" />
                                    </fo:block>
                                    <fo:block display-align="before" space-before="6mm">
                                        Page
                                        <fo:page-number />
                                        of
                                        <fo:page-number-citation ref-id="end-of-document" />
                                    </fo:block>
                                </fo:table-cell>
                            </fo:table-row>
                        </fo:table-body>
                    </fo:table>
                </fo:static-content>
                <fo:flow flow-name="xsl-region-body" border-collapse="collapse"
                    reference-orientation="0">
                    <fo:block>MONTHLY BILL REPORT</fo:block>
                    <fo:table table-layout="fixed" width="100%" font-size="10pt"
                        border-color="black" border-width="0.35mm" border-style="solid"
                        text-align="center" display-align="center" space-after="5mm">
                        <fo:table-column column-width="proportional-column-width(20)" />
                        <fo:table-column column-width="proportional-column-width(30)" />
                        <fo:table-column column-width="proportional-column-width(25)" />
                        <fo:table-column column-width="proportional-column-width(50)" />
                        <fo:table-body font-size="95%">
                            <fo:table-row height="8mm">
                                <fo:table-cell>
                                    <fo:block>Full Name</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block>Postal Code</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block>National ID</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block>Payment</fo:block>
                                </fo:table-cell>
                            </fo:table-row>
                            <xsl:for-each select="user-bill-data">
                                <fo:table-row>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="full-name" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="postal-code" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="national-id" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of
                                                select="format-dateTime(header/requestDetail/startDate,'[D01]/[M01]/[Y] [H01]:[m01]:[s01]','en',(),())" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell border="1pt solid black"
                                        padding-left="2pt" text-align="left" padding-right="2pt">
                                        <fo:block font="8pt Helvetica">
                                            <xsl:value-of
                                                select="format-dateTime(header/requestDetail/endDate,'[D01]/[M01]/[Y] [H01]:[m01]:[s01]','en',(),())" />
                                        </fo:block>
                                    </fo:table-cell>
                                    <xsl:value-of select="price" />
                                </fo:block>
                                </fo:table-cell>
                                </fo:table-row>
                            </xsl:for-each>
                        </fo:table-body>
                    </fo:table>
                    <fo:block id="end-of-document">
                        <fo:instream-foreign-object>
                            <svg width="200mm" height="150mm" version="1.1"
                                xmlns="http://www.w3.org/2000/svg">
                                <path
                                    d="M153 334
C153 334 151 334 151 334
C151 339 153 344 156 344
C164 344 171 339 171 334
C171 322 164 314 156 314
C142 314 131 322 131 334
C131 350 142 364 156 364
C175 364 191 350 191 334
C191 311 175 294 156 294
C131 294 111 311 111 334
C111 361 131 384 156 384
C186 384 211 361 211 334
C211 300 186 274 156 274"
                                    style="fill:yellow;stroke:red;stroke-width:2" />
                            </svg>
                        </fo:instream-foreign-object>
                    </fo:block>
                </fo:flow>
            </fo:page-sequence>
        </fo:root>
    </xsl:template>
</xsl:stylesheet>

这里是Java类,使用FOP转PDF

公共(public)最终类 PDFConverter {

private PDFConverter() {

}

private static final String RESOURCES_DIR;
private static final String OUTPUT_DIR;

static {
    RESOURCES_DIR = "src//main//resources//";
    OUTPUT_DIR = "src//main//resources//output//";
}

public static void main(final String[] args) {
    try {
        convertToPDF();
    } catch (FOPException | IOException | TransformerException e) {
        e.printStackTrace();
    }
}

public static void convertToPDF() throws IOException, FOPException, TransformerException {
    // the XSL FO file
    File xsltFile = new File(RESOURCES_DIR + "//template.xsl");
    // the XML file which provides the input
    StreamSource xmlSource = new StreamSource(new File(RESOURCES_DIR + "//data.xml"));
    // create an instance of fop factory
    FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
    // a user agent is needed for transformation
    FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
    // Setup output
    OutputStream out;
    out = new java.io.FileOutputStream(OUTPUT_DIR + "//output.pdf");

    try {
        // Construct fop with desired output format
        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

        // Setup XSLT
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));

        // Resulting SAX events (the generated FO) must be piped through to
        // FOP
        Result res = new SAXResult(fop.getDefaultHandler());

        // Start XSLT transformation and FOP processing
        // That's where the XML is first transformed to XSL-FO and then
        // PDF is created
        transformer.transform(xmlSource, res);
    } finally {
        out.close();
    }
}

最佳答案

参见 http://saxonica.com/html/documentation/using-xsl/embedding/jaxp-transformation.html关于如何确保 Saxon 被用作 Transformer,它说

If you want to be sure that Saxon (and not some other XSLT engine) is loaded to perform your transformations, you need to know the class name of Saxon's implementation of the JAXP TransformerFactory class. This depends on which Saxon edition you are using:

Any: net.sf.saxon.TransformerFactoryImpl. This will create a Saxon configuration based on the software and license file that are available at run-time on the classpath.

基于此,您可以将 TransformerFactory factory = TransformerFactory.newInstance(); 更改为 TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl(); 然后您的代码应该使用 Saxon。

另外,如果您使用 Saxon 9.8 HE,请不要忘记在您的 XSLT 代码中设置 version="3.0",因为它不支持在 version="1.0 的向后兼容代码中运行" 样式表。

关于java - xslt 函数 format-dateTime 在转换为 PDF 时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46725864/

相关文章:

Jtextfield 的 Java Swing 圆形边框

java - 在 Java REST Web 服务中访问部分多部分/表单数据发布请求

sql - 在 t-sql 中使用 .query() 只获取内部文本

xml - 如何删除 XSLT 中的特定子元素?

java - Android 抽屉布局显示在 fragment 内容下

java - 将 onMessage() 方法转换为原子操作

java - 既可选又可为空的 JAXB 元素

android - 如何在全屏启动画面中去除图像周围的白色边框

xml - 支持 XPath 2.0 的 Java XSLT 处理器

java - 如何从 Java 应用程序使用 XSLT 3.0?