[转]基于模板和XML在BS结构应用中生成word文件

现在的各类应用系统中时常会需要动态生成Word文件,解决比较常见的两种方法是:
1.      利用Word提供的COM自动化接口控制Word生成文档
2.      利用Word对html的支持,制作html文件,并设置其contentType为"application/msword",使浏览器调用word打开

第一种方法靠Word进程实际完成文件生成工作,而Word并为设计为在服务器端处理并发调用,所以这种方法只适合单机应用。另外,如果要生成比较复杂的word文件,相应的代码会非常烦琐,排版和调试也需要花大量时间。
第二种方法的致命问题是html文档中无法保存二进制数据,比如图片,如果在服务器端生成一堆文件,即难以在浏览器中显示,也无法让用户直接下载。

比较完善的解决办法是基于WordML来生成word文件。WordML是微软为Word设计的xml架构,其完整语法可以在MSDN上找到。按照这个语法生成xml文件,可以在文档中随意得到各种word支持的格式。特别需要指出的是可以方便的在文件中内嵌图片,其语法基本是这样:


<w:pict>
    <v:shapetype id="_x0000_t75" ...>
    ... VML shape template definition ...
    </v:shapetype>
    <w:binData w:name="wordml://02000001.jpg">/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+4ADkFkb2JlAGTAAAAAAf/b
AIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoKDBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxsc
... 更多Base6编码的图片文件数据
    </w:binData>
    <v:shape id="_x0000_i1025" type="#_x0000_t75"
      style="width:212.4pt;height:159pt">
         <v:imagedata src="wordml://02000001.jpg"
           o:title="Image title"/>
    </v:shape>
</w:pict>

其关键是图片的实际数据以base64编码之后放在<w:binData></w:binData>标记之间。 如果你看了MSDN上的WordML语法,会发现它非常复杂。这不奇怪,因为Word有非常多的功能,但要写程序根据这么多定义来生成文档就比较费事了。不过我们可以利用模板文件来解决这个问题。 同我们动态生成网页一样,要动态生成的word文件也有相当多部分是固定不变的,并且复杂的版面、格式一般都在这些固定不变的部分中。所以借用生成网页的思路,我们可以在word中先根据需要的版面和格式,结合一些虚拟的数据做出模板文件,然后将这个模板文件保存为xml格式,再在xml文件中找到那些虚拟的数据对应的文本,将它们替换为将采用的后台处理技术的数据处理指令,这样我们就可以在服务器端结合模板文件和数据库查询,生成word文件了。 下面举一个例子。假设我们采用JSP进行word文件生成,首先制作模板文件如下:

连宋个人简历


本人概况


姓名


连宋


出生日期


1937年7月7日


性别



证件类型


身份证


学历


大学本科


证件号码


41043219700707011


婚姻状况


已婚


期望月薪


面议


户口所在地

然后将这个文件保存为xml格式,我们将得到如下内容的xml文件:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?"Word.Document"?>
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:st1="urn:schemas-microsoft-com:office:smarttags" w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve"><o:SmartTagType o:namespaceuri="urn:schemas-microsoft-com:office:smarttags" o:url="" o:name="chsdate"/><o:DocumentProperties><o:Title>个人简历</o:Title>
... ...
<w:rPr><w:rFonts w:hint="fareast"/><wx:font wx:val="宋体"/></w:rPr><w:t>连宋个人简历</w:t></w:r><w:proofErr w:type="gramStart"/><w:r><w:rPr><w:rFonts w:hint="fareast"/><wx:font wx:val="宋体"/></w:rPr>
... ...
<w:pict><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"/><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"/><v:f eqn="sum @0 1 0"/><v:f eqn="sum 0 0 @1"/><v:f eqn="prod @2 1 2"/><v:f eqn="prod @3 21600 pixelWidth"/><v:f eqn="prod @3 21600 pixelHeight"/><v:f eqn="sum @0 0 1"/><v:f eqn="prod @6 1 2"/><v:f eqn="prod @7 21600 pixelWidth"/><v:f eqn="sum @8 21600 0"/><v:f eqn="prod @7 21600 pixelHeight"/><v:f eqn="sum @10 21600 0"/></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/><o:lock v:ext="edit" aspectratio="t"/></v:shapetype><w:binData w:name="wordml://02000001.jpg">/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+4ADkFkb2JlAGTAAAAAAf/b
... ...
</w:binData><v:shape id="_x0000_i1025" type="#_x0000_t75" style="width:75pt;height:75pt"><v:imagedata src="wordml://02000001.jpg" o:title="cathy"/></v:shape></w:pict>
... ...
</w:sectPr></wx:sub-section></wx:sect></w:body></w:wordDocument>

接下来首先将这个文件按照xml格式进行排版,然后在其中找到需要动态生成的文字部分(WordML中文字以<w:t></w:t>标记起始),将其替换为从后台取数据生成文字的JSP指令,再在文件头部添加JSP控制指令,得到如下的xml文件: 


<%@ page language="java" errorPage="/error.jsp" pageEncoding="GBK" contentType="application/msword;charset=UTF-8" %><%response.setHeader("Content-Disposition", "attachment; filename=resume.doc");%><?xml version="1.0" encoding="UTF-8" standalone="yes"?>


<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>


<?"Word.Document"?>
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve">
 <o:DocumentProperties>
  <o:Title>个人简历</o:Title>
... ...
 <w:body>
  <wx:sect>
   <wx:sub-section>
    <w:p>
     <w:pPr>
      <w:pStyle w:val="a5"/>
      <w:rPr>
       <w:rFonts w:hint="fareast"/>
      </w:rPr>
     </w:pPr>
     <w:r>
      <w:rPr>
       <w:rFonts w:hint="fareast"/>
       <wx:font wx:val="宋体"/>
      </w:rPr>
      <w:t><c:out value="${command.name}"/>个人简历</w:t>
     </w:r>
    </w:p>
... ...
         <w:pict>
          <v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
           <v:stroke joinstyle="miter"/>
           <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
           <o:lock v:ext="edit" aspectratio="t"/>
          </v:shapetype>
          <w:binData w:name="wordml://02000001.jpg"><c:out value="${command.portraitBASE64}"/></w:binData>
          <v:shape id="_x0000_i1025" type="#_x0000_t75" style="width:75pt;height:75pt">
           <v:imagedata src="wordml://02000001.jpg" o:title="portrait"/>
          </v:shape>
         </w:pict>
... ...
 </w:body>
</w:wordDocument>

将这个文件以jsp后缀保存,就可以在J2EE系统中配合后台程序生成word文件了。如果你需要浏览器提示保存这个文件,而不是在浏览器中打开,需要在文件头部加入这句:
response.setHeader("Content-Disposition", "attachment; filename=resume.doc");
有很多免费的第三方库可以用于生成图片文件BASE64编码,JDK中也有BASE64 Encoder。

更简单的方法是在用word制作模板文件时直接在需要动态生成的部分输入jsp指令,然后再保存为xml文件,但要注意检查word保存为xml文件后有没有将jsp指令拆散或插入格式标记。 以上以JSP+JSTL为例,换成其它后台技术,比如Velocity,或者ASP、PHP,原理也是相同的。 实际上,在需要生成Word文件的应用中,多数时候需要套用固定的格式,这样本文所解释的方法就更加合适。

 

时间: 2024-08-03 19:05:56

[转]基于模板和XML在BS结构应用中生成word文件的相关文章

基于模板和XML在BS结构应用中生成word文件

word|xml|模板 现在的各类应用系统中时常会需要动态生成Word文件,解决比较常见的两种方法是: 1.       利用Word提供的COM自动化接口控制Word生成文档 2.       利用Word对html的支持,制作html文件,并设置其contentType为"application/msword",使浏览器调用word打开 第一种方法靠Word进程实际完成文件生成工作,而Word并为设计为在服务器端处理并发调用,所以这种方法只适合单机应用.另外,如果要生成比较复杂的w

【Win 10应用开发】Adaptive磁贴模板的XML文档结构

原文:[Win 10应用开发]Adaptive磁贴模板的XML文档结构 在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win 10的API中也是支持的,此外,Win10 App还支持全新的自适应磁贴模板,本文老周就给大家先讲一下基本结构,下一篇文章中咱们再说一说复杂排版.   应用程序的图标可以分为两类:第一类是应用商店上专用的,就是你的应用提交到商

sqlserver 存储过程-【求助BS】进行BS开发,要生成Word文档,目录需要手工生成,怎么查找标题所在页码

问题描述 [求助BS]进行BS开发,要生成Word文档,目录需要手工生成,怎么查找标题所在页码 进行BS开发,要生成Word文档,目录需要手工生成,怎么查找标题所在页码.怎么弄,求帮助啊大神!

服务器-BS系统 java web打印word文件或者word文件流

问题描述 BS系统 java web打印word文件或者word文件流 BS系统.在服务器存有多个word文件.要求在页面点击打印直接打印. 用户点击打印能够选择打印那些文件,并且能够控制份数. (PS:文件是用户上传的,无法写死) 解决方案 客户端安装word,然后下载打印,否则没办法做到精确.浏览器有自己的打印设置.

进行BS开发,要生成Word文档,目录需要手工生成,怎么查找标题所在页码

问题描述 进行BS开发,要生成Word文档,目录需要手工生成,怎么查找标题所在页码 进行BS开发,要生成Word文档, 文档中的目录(里面的含有20个标题)需要手工生成,怎么查找标题所在页码? 我想查找到标题所在页码,然后通过书签插入到目录标题后面.

XML在BS架构开发中的应用

动机: 1. JSP构造页面太痛苦. 代码嵌入页面导致页面臃肿, 逻辑复杂, 不易编 辑. 2. 程序员和美工的接口必须精确定义. 复杂的嵌套输出必须构造复杂的显示 类作为接口. 3. 调试JSP必须等到前端程序结束才能看到效果. 3. 调试JSP效率极低, 一点点小的修改都会引起jsp的重新编译. 新的XML的解决方案: 1. 一个servlet做统一管理. 接受url请求, 映射到对应的程序bean. 2. 程序bean只产生XML, 由servlet统一用对应的XSL转换为html. 好处

基于PHP与XML的PDF文档生成技术

xml 摘要 本论文简要介绍了PHP.XML.PDF等技术的原理以及它们的应用情况.力图运用PHP面向对象的特性,构建出一套基于PHP和XML的在线PDF文档生成系统.文中详细探讨了整个系统的组成部分以及各自的实现过程.并在最后给出一个运用这套系统实现的动态创建报表的实例. AbstractThis article introduced the fundamentls of PHP,XML and PDF and their application situation at present,ex

基于PHP与XML的PDF文档生成技术_php基础

摘要<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 本论文简要介绍了PHP.XML.PDF等技术的原理以及它们的应用情况.力图运用PHP面向对象的特性,构建出一套基于PHP和XML的在线PDF文档生成系统.文中详细探讨了整个系统的组成部分以及各自的实现过程.并在最后给出一个运用这套系统实现的动态创建报表的实例. Abstract This article introdu

基于AJAX的动态树型结构的设计与实现

ajax|动态|设计|树型结构 <B>摘 要</B>:简要介绍了一种通用的,动态树型结构的实现方案,该方案基于Asynchronous JavaScript and XML,结合Struts框架设计实现了结构清晰.扩展性良好的多层架构,数据存储于数据库,结合XML描述树的节点信息,使得任何按预定的XML文档描述的信息都可以通过动态树来展现.<br /><table border="0" cellspacing="0" cel