在 ASP.NET 中为 PDF 转换目的执行 xHTML 到 xHTML 转换。





2.00/5 (1投票)
本文讨论了用于 PDF 输出目的的动态 xHtml 到 xHtml XSL 转换。
引言
将 HTML 页面转换为不同格式,尤其是 PDF,已成为 Web 开发人员广泛采用的常规操作。这个过程本身相当直接,因为 Web 上有大量的 PDF 开发库和服务。但是,有一天,您可能不仅需要制作页面的 PDF 副本,还需要自动对生成的 PDF 输出进行一些修改(例如,您可能想访问页面上的 SVG 数据)。在本文中,我将演示一个在 ASP.NET 中使用一些 .NET 和 XSL 技巧以及 PD4ML PDF 库来完成此任务的简单示例。
步骤 1:搜索 xHTML 标记
ASP.NET 非常适合轻松创建复杂的页面。但是,所有这些控件和其他东西与渲染并发送到客户端的 xHTML 标记几乎没有关系。因此,我们要做的第一件事就是以某种方式将其揭示出来。标记是借助生命周期的“Render
”方法创建的,所以我们需要重写该方法。
protected override void Render(HtmlTextWriter output)
{
//Creating String and Html writers to copy the created HTML markup
StringWriter writer = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
//Creating HTML markup with the help of our "fake" HTmlTextWriter
base.Render(htmlWriter);
//Coping the markup to the string and saving it to the disk
string htmlMarkup = writer.ToString();
StreamWriter XMLwriter = new StreamWriter(Server.MapPath("Htmloutput.xml"));
XMLwriter.Write(htmlMarkup);
XMLwriter.Close();
//Creating actual HTML markup for display
output.Write(htmlMarkup);
}
步骤 2:准备进行 XSL 转换
现在我们需要准备我们的 XSLT 文件。ASP.NET 会生成有效的 xHTML 标记,因此我们只需根据我们的需求对其进行更改,但仍可能遇到一些问题。
- 首先,不要忘记,xHTML 标记使用默认的
xmlns=http://www.w3.org/1999/xhtml
命名空间,因此我们需要在 XSLT 文件中创建一个前缀,以访问节点。这就是为什么我们在 XSLT 文件中添加xmlns:xhtml=http://www.w3.org/1999/xhtml
字符串,并将 xhtml 添加到“exclude-result-prefixes”中以从结果文档中删除它的原因。 - 其次,现在我们可以进行转换了,但还有另一个问题:输出文档中有大量的
xmlns=""
节点。要摆脱它们,请将xmlns=http://www.w3.org/1999/xhtml
添加到 XSLT 文件命名空间声明中。 - 第三,HTML 页面包含纯文本,而 XML 不允许纯文本,因此 XSLT 不会处理它。要摆脱文本节点,请在 XSLT 样式表中放置
<xsl:template match="xhtml:body//text()">
模板。<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="msxsl xhtml"> <!--the rest of the xsl file --!>
步骤 3:创建 PDF 文件
这就是我们达到最终目标的地方。我们所要做的就是执行 XSL 转换并创建 PDF 文件。我将使用 – PD4ML HTML to PDF 转换库,因为它可以在 Java、PHP、Ruby 等不同的编程语言中使用。我将使用 MemoryStream
,因为我不想将任何中间数据保存到硬盘。
protected void MakePDFButton_Click(object sender, EventArgs e)
{
//Doing XSL transformation
string XSLTFile = Server.MapPath("XSLTFile.xslt");
string XMLFile = Server.MapPath("HTMLoutput.xml");
// Allowing DTD in our xHTML markup
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
XmlReader reader = XmlReader.Create(XMLFile, settings);
//Transforming the initial HTML markup and outputting it to MemoryStream
//object instance for further PDF conversion
XslCompiledTransform XSLTransform = new XslCompiledTransform();
XSLTransform.Load(XSLTFile);
Stream memoryStream = new MemoryStream();
XSLTransform.Transform(reader, null, memoryStream);
//Flushing the stream and positioning the cursor at the beginning
//of the data in the stream.
memoryStream.Flush();
memoryStream.Position=0;
reader.Close();
//Showing the markup on the page
StreamReader streamReader=new StreamReader(memoryStream);
string output=streamReader.ReadToEnd();
HTMLoutput.Text = Server.HtmlEncode(output);
//Converting result HTML page to PDF
PD4ML PDFcreator = new PD4ML();
PDFcreator.PageSize = PD4Constants.A4;
PDFcreator.DocumentTitle = "The result PDF file";
string path=Server.MapPath("Output.pdf");
StreamWriter streamWriter = new StreamWriter(path);
memoryStream.Position = 0;
PDFcreator.render(memoryStream as MemoryStream, streamWriter);
//Closing all the streams
streamReader.Close();
streamWriter.Close();
}
结论
就是这样!现在让我们来一个简短的总结。
- 使用重写的“
Render
”方法来操作和获取 xHTML 标记。 - 使用自定义 XML 命名空间前缀来访问未加前缀的 xHTML 节点。
- 使用一点 xslt“
xmlns=http://www.w3.org/1999/xhtml
”技巧来摆脱大量的xmlns=""
节点。 - 如果您需要摆脱未被任何元素包装的纯文本,请使用
<xsl:template match="xhtml:body//text()">
。
我希望 Visual Studio 开发人员“想当然”的有效 xHTML 标记与上面描述的几个简单技巧相结合,将为您提供无数种操作文档数据的可能性。
历史
- 2011 年 3 月 1 日:初始帖子