
私のプロジェクトの1つで、クライアント用の契約文書を自動的に生成する必要がありました。 契約は約10ページの長さの法的文書であり、テンプレートです。特定のクライアントのデータが適切な場所で置き換えられます。
挑戦する
主な要件は次のとおりです。
複雑な様式化されたdocまたはdocxドキュメントで、マークされた場所に必要な情報を表示します。
それらはさらに洗練され拡張されました。
- 複雑な様式化されたdocxドキュメントで、マークされた場所にデータを表示します。
- 出力マークアップは、スクリプトレットのように見えるはずです:
${}, <%%>, <%=%>
。 - 出力データはオブジェクトの場合があります。 フィールドにアクセスする機能が必要です。
- 出力には、Groovy、JavaScriptのいずれかのスクリプト言語を使用します。
- テーブルにオブジェクトのリストを表示し、各セルにフィールドを表示できるようにする必要があります。
既存のソリューション
フィールドで利用可能な製品(私はJavaプラットフォームについて話している)がタスクを解決しないことが判明しました。 製品の概要は次のとおりです。
ジャスパーレポート
テンプレートとして、xmlマークアップファイル* .jrxmlを使用します。 ドキュメントマークアップファイル+データ(データベースおよびマップパラメーターの両方)がプロセッサーに渡され、PDF、XML、HTML、CSV、XLS、RTF、TXTのいずれかの形式が生成されます。
合わなかった:
- これは、jrxmlファイルを生成するための視覚的なツールであるiReportを使用しても、WYSIWYGではありません。
- 複雑なテンプレートを作成してスタイルを設定するには、JasperReports APIをよく勉強する必要があります。
- 目的の形式で表示されません。 PDFも作成できますが、後で出力ドキュメントを編集できるようにしたいと思います。
Docx4java
Java-APIを使用してdocx-、pptx-、xlsx-documentsのコンポーネントを操作するためのツール。
合わなかった:
- Docx4Javaのドキュメントには、私の要件に一致するケースはありません。 最も簡単な置換を行うXMLUtils.unmarshallFromTemplate関数の簡単な言及があります。
- 出力の繰り返し処理は、XPath リンクを使用してXMLソースを介して実装されます。
Apache POI
Java APIを使用して、doc-、ppt-、xls-documentsのコンポーネントを操作するためのツール。 これらの形式のドキュメントからデータを取得するために最初に作成されました。
合わなかった:
- タスクに対する解決策はありません。
問題解決
面白かったです:)
1.ドキュメントのコンテンツはxmlとして保存され、zipアーカイブに圧縮されます。 従来のJDK 6のジッパーは明示的なエンコード(明らかにファイル名)をサポートしていないため、解凍は困難です。 アーカイブの際に、docxが無効になりました。 コンテンツをパックするときに、対応するパラメーターでGroovy AntBuilderラッパークラスを使用する必要がありました。
2. MS Wordに入力されたテキストは、プログラムによって断片に分割され、xmlタグの異なるグループに配置されるため、生成されたxmlガスケットからテンプレートを削除する問題を最初に解決する必要がありました。 このタスクでは、正規表現を使用しましたが、SAXパーサーよりも高速に見えました(ただし、パフォーマンスは測定しませんでした)。
3. Groovyをスクリプト言語として使用することにしました。その理由は、その単純さ、Javaの性質、およびコアに含まれるテンプレートプロセッサです 。 彼には興味深い困難もありました。 10枚の小さなドキュメントであっても、2つのスクリプトレット間の行の長さの制限に簡単に到達できることが判明しました。 スクリプトレットの間にあるすべてのテキストをUUID文字列で置き換え、Groovyテンプレートプロセッサを実行し、最後にのみUUID文字列を元のXMLピースで置き換えなければなりませんでした。
これらの困難を克服して、私は実際にプロジェクトを試しました。 うまくいきました!
英語のプロジェクトサイトを作成して公開しました。
プロジェクトの住所: snowindy.github.com/scriptlet4docx
APIの使用例
HashMap<String, Object> params = new HashMap<String, Object>(); params.put("name", "John"); params.put("sirname", "Smith"); DocxTemplater docxTemplater = new DocxTemplater(new File("path_to_docx_template/template.docx")); docxTemplater.process(new File("path_to_result_docx/result.docx"), params);
プロジェクトのWebサイトにアクセスすると、ここで終了できます...
しかし、理解を深めるために、「スクリプトレットのタイプの説明」の最も興味深いセクションを翻訳します。
スクリプトレットの種類、詳細
免責事項: テンプレートを使用する場合、GroovyテンプレートプロセッサはすべてのスクリプトレットをGroovyコードに変換し、スクリプトレット間のテキストは次のように表示されます
out.print('template_text')
$ {データ}
データをoutに
out.print(data)
同等:
out.print(data)
<%=データ%>
データをoutに
out.print(data)
同等:
out.print(data)
<%any_code%>
スクリプトレット内でコードを実行しても何も表示されません。 条件付き出力に使用できます:
<% if (cond) { %> , "cond == true" <% } else { %> , "cond != true" <% } %>
$ [@ listVar.field]
これは最も興味深い種類のスクリプトレットです! docxドキュメント内のテーブルにオブジェクトのリストを表示するために使用されます。 テーブルセル内で使用する必要があります。
たとえば、Personオブジェクトのリストがあります。 オブジェクトには、「名前」と「アドレス」の2つのフィールドがあります。 2列のテーブルにリストを表示します。
- 入力値マップで「personList」パラメーターを作成すると、オブジェクトのリストが参照されます。
- docxドキュメントに2つの列と1つの行を持つテーブルを作成します。
-
$[@person.name]
は最初のセルに入力する必要があります。$[@person.address]
番目。 - すべての準備ができたら、personListリストがテーブルに印刷されます。
ライブテンプレートの例
ここにあります: link
プロジェクト開発
docxテンプレートの処理に対する新しいアプローチを実際に考案した場合、それを普及させたいと思います。
このプロジェクトには次のような努力が必要です。
- フルキャッシュ
- リストでのスクリプトレットのサポート
- ストリーミングAPIを実装する
英語圏の聴衆にプロジェクトを配布する際のアドバイスをうれしく思います!