【发布时间】:2017-10-13 08:41:35
【问题描述】:
我对 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
公共最终类 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();
}
}
}
【问题讨论】:
-
你能告诉我们你在课堂路径上有哪个撒克逊版本吗?您的样式表显示
version="1.0"和 Saxon 9.8 HE 例如不会运行它,尽管这会导致不同的错误消息。你如何运行 XSLT,你确定它是被 FOP 用作 XSLT 处理器的 Saxon 吗? -
@MartinHonnen 我在我的课程路径中使用 Sason-HE-9.8.0-5.in。为了运行 XSLT,我有一个 java 类,它使用 FOP 转换为 PDF。
-
正如我所说,如果是 Saxon 9.8 HE 运行
version="1.0"样式表,它会引发一个错误,即它不支持向后兼容性,因此我认为您的 Java 类不使用 Saxon而是用 Xalan 来转换样式表,这样就找不到format-dateTime并且()会引发该语法错误。因此,为 Java 或 FOP 添加一个标签并显示 Java 代码,以便熟悉该代码的人可以建议如何确保使用 Saxon 而不是 Xalan。您还需要将 XSLT 版本更改为3.0。 -
还请注意,您可以通过显示从 newInstance() 方法返回的类名来检查已加载的 TransformerFactory;您还可以使用系统属性 jaxp.debug 来显示诊断信息。但是,除非您真的希望您的应用程序使用它在类路径上找到的任何 XSLT 处理器运行,否则最好不要依赖 JAXP 来找到正确的处理器,而是显式加载它。
标签: java xml xslt-2.0 saxon apache-fop