在现代软件开发中,自动化文档生成是一个常见的需求,尤其是在需要生成发票或与Web服务/服务器页面输入参数相关的简单动态文档/报告时。本文将介绍一种结合输入参数、图像和静态本地化字符串生成PDF文档的方法。
下面的图像描述了这种解决方案背后的思想:
用户向Web服务提交请求。该请求被序列化为XML,并与静态本地化XML合并。结果通过一个XSLT样式表,输出为XSL-FO文档。XSL-FO(可扩展样式表语言-格式化对象)是一种用于将XML数据格式化为屏幕、纸张或其他媒体输出的语言。它可以通过FO.NET库解析以生成PDF文档。
下面的UML图表示了解决方案中最重要的类之间的关系。
每个类及其职责的简短描述:
在web.config中,有一个小的配置节:
<pdfPrinterConfiguration>
<settings xsltFolderPath="~/App_Data/Resources/XSLT/" localizationXmlFolderPath="~/App_Data/Resources/XML/" defaultCulture="en-US" defaultDateFormat="MM/dd/yyyy" pdfOutputFolder="~/GeneratedDocuments/" />
</pdfPrinterConfiguration>
这些设置告诉应用程序XSLT文件、本地化文件的位置,应用程序的默认文化,日期时间格式,以及PDF文件的保存位置。
决定用一个简单的WCF服务来测试PDF打印机核心。首先,让创建一个IPrintableDocument类:
[Serializable, DataContract(Namespace = "http://Schemas/PdfPrinter/Common")]
public class Document : IPrintableDocument
{
[DataMember(IsRequired = true)]
public string Description;
public string ToXml()
{
return ObjectXmlSerializer.SerializeObjectToXmlFormattedString(this);
}
}
然后,让编写一个简单的Web服务,它包含请求和响应:
[ServiceBehavior(Namespace = "http://Schemas/PdfPrinter/WebServices")]
public class PdfPrinterService : IPdfPrinter
{
public PdfPrinterResponse Print(PdfPrinterRequest request)
{
return PdfPrinterFacade.PrintPdf(request);
}
}
接下来,实现XSLT和本地化XML文件,并以Document类命名。将Document.xslt放在"~/App_Data/Resources/XSLT/"文件夹下。这是一个简单的XSLT,展示了XSL-FO的一些强大功能。然后,编写了一个简单的本地化XML文件Document.xml,并将其放在"~/App_Data/Resources/XML/"文件夹下。
让用Document.Description = "Hello"调用Web服务。所有输入数据都合并在一个XML文档中,如下所示:
<PdfPrinter>
<Document>
<Description>
Hello
</Description>
</Document>
<culture language="en-US">
<label id="Footer" text="This documents has been auto-generated with Pdf Printer Service"/>
<label id="Page" text="Page " />
<label id="Of" text="of " />
<label id="Message" text="You sent the following message:" />
<label id="EmptyMessage" text="- Empty message -" />
<label id="Date_Header_1" text="Date" />
<label id="LongWord_Header_2" text="Very Long Word" />
<label id="Decimal_Header_3" text="Decimal" />
<label id="Integer_Header_4" text="Integer" />
<label id="Total" text="Total" />
<label id="Date_Field_1" text="11/02/1984" />
<label id="LongWord_Field_2" text="ThisIsAVeryVeryLongBreakedWord" />
<label id="Decimal_Field_3" text="1234.5678" />
<label id="Integer_Field_4" text="3" />
</culture>
</PdfPrinter>
然后,XSLT文件通过查询前面的XML内容生成XSL-FO文档。它使用了一个辅助扩展类(PdfPrinter.Core.Common.XsltExtensionService),简化了一些常见操作。