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>"
. おそらく、ノード エンジンのいくつかのスイッチが役立つでしょうか?
私の質問は、XSLT を使用して XML から対象のデータを抽出し、CSS を使用して適切なページ付きドキュメントとして PDF をフォーマットし、無料の商用ライセンスを持つソフトウェアを使用して、プログラムで XML ファイルを PDF に変換する方法を教えてください。私はpaged.js
それを達成する必要がありますか?
私のファイルについて: 私の XML ファイルでは、XML から特定のデータを抽出するローカル XSL ファイルを参照しています。重複を削除し、日付順に並べ替えます。この XSL ファイルはローカル CSS ファイルを参照して、優れた書式設定と「ページング」属性を提供します。スクリプト ドキュメントのように、 XSL リファレンスもpaged.js
スクリプトおよび関連する CSS に記載されています。
weasyprint
、 、 、htmldoc
、html5-to-pdf
との間で試してみましたが、wkhtmltopdf
成功しませんでした。
私はどんな提案にもオープンです。
編集: 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
(下記参照) に保存されます。Result
この xml ファイルには、必要な数のフィールドを入れることができます。私のファイルには 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.css
ます(「参考文献」を参照)。paged.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
ますか?