2

我正在尝试使用 XSLT 和 CSS 将 XML 报告转换为 PDF。此 PDF 应在页脚中包含特定的页码,例如特定表格后的分页符。

根据我的发现,这可以使用 CSS3“at-attributes”来实现“分页媒体”(例如@page)。但是,如果我理解正确,我可能很难找到解释这些属性以创建 PDF 的工具(更不用说它需要先从 XML 转换)。

我发现我可以使用paged.js脚本让它在浏览器中运行,但它只有在我运行本地服务器(例如live-server)时才有效,因为所有 Web 浏览器中都有一些本地文件限制。我可以(有点)使用命令行开关来克服这个问题,--allow-file-access-from-files但它会在渲染完成之前打印文档(看起来浏览器不等待paged.js脚本完成)。我尝试了不同的开关:chrome.exe --headless --disable-gpu --allow-file-access-from-files --run-all-compositor-stages-before-draw --virtual-time-budget=100000 --print-to-pdf="<destination>" "<source>". 也许节点引擎的一些开关可以提供帮助?

我的问题是如何使用具有免费商业许可的软件以编程方式将 XML 文件转换为 PDF,使用 XSLT 从 XML 中提取感兴趣的数据,并使用 CSS 将 PDF 格式化为正确的分页文档?我需要paged.js完成它吗?

关于我的文件:在我的 XML 文件中,我引用了从 XML 中提取特定数据的本地 XSL 文件;他们删除重复项并按日期对它们进行排序。此 XSL 文件引用本地 CSS 文件以提供良好的格式和“分页”属性。XSL 还参考paged.js了脚本和相关的 CSS,如脚本文档中所示。

我试过,在其他之间,,,,但weasyprint没有成功。htmldochtml5-to-pdfwkhtmltopdf

我愿意接受任何建议。


编辑:我正在试验 XSL-FO(正如评论中所建议的那样),我不得不承认它工作得很好。在我看来,页面控件比 CSS 更具可读性。我现在看到的唯一问题是它需要额外的安装(Apache FOP 和 Java 运行时环境)。在我的场景中,在 .NET 中使用 FOP 会更好。

无论如何,我决定更详细地描述我使用 Chrome 作为渲染器的基于 CSS 的解决方案,因为它不需要额外的安装程序(或者至少我认为是这样)。我已经花了一些时间在它上面,似乎它几乎可以工作了。也许有人会发现问题出在哪里,然后它将成为使用 CSS 的分页媒体的一个非常好的解决方案。

完整transform.xsl的文件是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <html>
        <head>
            <title>Summary</title>
            <link href="css/style.css" rel="stylesheet" type="text/css"/>
            <link href="css/interface.css" rel="stylesheet" type="text/css"/>
            <script src="js/paged.polyfill.js"/>
        </head>
        <body>
            <h1>Summary</h1>
            <table class="summary">
                <tr><td>Total Quantity:</td><td><xsl:value-of select="count(Results/Result)"/></td></tr>
                <tr><td>Passed:</td><td><xsl:value-of select="count(Results/Result[Status='Pass'])"/></td></tr>
                <tr><td>Failed:</td><td><xsl:value-of select="count(Results/Result[Status='Fail'])"/></td></tr>
            </table>
            <br />
            <xsl:apply-templates/>
        </body>
    </html>
</xsl:template>

    <xsl:template match="Results">
        <table class="results">
            <tr>
                <th>Serial Number</th>
                <th>Test Result</th>
                <th>Date</th>
                <th>Time</th>
            </tr>
            <xsl:for-each select="Result">
                <tr>
                    <xsl:attribute name="class"><xsl:value-of select="./Status"/></xsl:attribute>
                    <td><xsl:value-of select="./SerialNumber"/></td>
                    <td><xsl:value-of select="./Status"/></td>
                    <td><xsl:value-of select="./Date"/></td>
                    <td><xsl:value-of select="./Time"/></td>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>

</xsl:stylesheet>

在我的style.css我有@page如下规则。我的原始文件中有更多内容,但在这里并不重要。

@page {
    size: A4;
    margin: 2cm 1cm;

    @top-left {
        content: "Summary Continued...";
        font-size: 15px;
    }

    @bottom-center{
        content: "Page " counter(page) "/" counter(pages);
        font-size: 15px;
    }
}

@page :first {
    @top-left {
        content: "";
    }
}

数据存储在Reports.xml(见下文)。在这个 xml 文件中,您可以放置​​任意数量的Result字段。我的文件中有 200 个结果,但我在这里截断了它以使其更清晰。

<?xml version="1.0" encoding="iso-8859-1" ?><?xml-stylesheet type="text/xsl" href="xsl/transform.xsl"?>

<Results>
    <Result ID="0">
        <SerialNumber>8652280431</SerialNumber>
        <Status>Fail</Status>
        <Date>05-Mar-21</Date>
        <Time>08:56:23</Time>
    </Result>
    <Result ID="1">
        <SerialNumber>11124002643</SerialNumber>
        <Status>Fail</Status>
        <Date>05-Mar-21</Date>
        <Time>08:56:23</Time>
    </Result>
.
.
.
    <Result ID="200">
        <SerialNumber>6616001379</SerialNumber>
        <Status>Fail</Status>
        <Date>05-Mar-21</Date>
        <Time>08:56:23</Time>
    </Result>
</Results>

我的文件中也有,interface.csspaged.polyfill.js文档中所述请参阅 参考资料transform.xsl)。

当我Results.xml在 Chrome 中使用命令打开时,chrome.exe --allow-file-access-from-files <file path>它的工作方式为例外(见下图)。

图片

当我尝试Results.xml使用命令在 Chrome中打印我的时,chrome.exe --headless --disable-gpu --allow-file-access-from-files --run-all-compositor-stages-before-draw --virtual-time-budget=100000 --print-to-pdf=<destination> <source>它会产生意外的结果。仅生成几页,总页数 ( counter(pages)) 在页脚中返回 0(见下图)。

图片

所以也许有人会想办法让它工作。

也许--js-flags会成功?或者也许我应该添加/更改一些东西paged.polyfill.js

4

0 回答 0