用 XPCOM 在客户端动态生成 OpenOffice 文档(2)

来源:developerWorks 中国 作者:Stefanus Wiguna
  

ODF 规范提供了关于定义和格式化样式的所有信息(参见 参考资料)。一旦样式表文件准备就绪,就可以在 Firefox Extension 环境中进行格式转换了。使用扩展管理器,定位用来进行格式转换的样式表文件。清单 5 是一个示例。


清单 5. 定位 XSLT 文件
// locate stylesheet file
var xslfile = em.getInstallLocation(eid).getItemFile(eid, oopath + ooxslt);

            

接下来,加载这个样式表文件。


清单 6. 加载 XSLT 文件
				
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
 .createInstance(Components.interfaces.nsIFileInputStream);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
 .createInstance(Components.interfaces.nsIScriptableInputStream);

var xsldata = "";
fstream.init(xslfile, -1, 0, 0);
sstream.init(fstream); 
var tmp = sstream.read(4096);
while (tmp.length > 0) {
 xsldata += tmp;
 tmp = sstream.read(4096);
}
sstream.close();
fstream.close();

var parser = new DOMParser();
var xsldoc = parser.parseFromString(xsldata,"text/xml");
            

可以用这个样式表来将内容转换为 ODF。在下面的示例中,xmldoc 是包含现有内容的 XML 文档。


清单 7. 用 XSLT 将内容转换为 ODF
				
var xsltprocessor = new XSLTProcessor();
xsltprocessor.importStylesheet(xsldoc);
var newcontentdoc = xsltprocessor.transformToFragment(xmldoc,document);
            

现在,可以用新内容更新 content.xml 了。要制作一个有效的 OpenOffice content.xml,需要包含恰当的内容头和内容尾(参见 图 2)。


清单 8. 用新内容更新 content.xml
				
// prepare new content
var contentbody = (new XMLSerializer()).serializeToString(newcontentdoc);
var newcontent = xmlheader + contenthead + contentbody + contenttail

// update content.xml
var contentfile = em.getInstallLocation(eid).getItemFile(eid, oopath + "content.xml");
var fstream = Components.classes["@mozilla.org/network/file-output-stream;1"]
 .createInstance(Components.interfaces.nsIFileOutputStream);
fstream.init(contentfile, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666, 0);
fstream.write(newcontent, newcontent.length);
fstream.close();
            

现在,content.xml 已经更新好了。在下面的章节,我们将构建一个新的 OpenOffice 文档。

构建 OpenOffice 文档

要构建一个新的 OpenOffice 文档,需要创建一个新的 OpenOffice 归档文件并将 content.xml 和其他请求文件添加到这个归档文件中。本文的这个示例使用 nsIZipWriter XPCOM 接口来达到这个目的。

首先是要创建这个归档文件并将它保存到用户机器上的某个地方。下面的示例将这个新文件保存到了桌面区域,如清单 9 所示。根据要求,可能还需要创建一个临时文件或将它保存到其他地方。


清单 9. 创建一个新的 OpenOffice 文档归档文件
				
var odtfile = Components.classes["@mozilla.org/file/directory_service;1"]
 .getService(Components.interfaces.nsIProperties)
 .get("Desk", Components.interfaces.nsIFile);
odtfile.append("new.odt");
odtfile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);

var zipWriter = Components.Constructor("@mozilla.org/zipwriter;1", "nsIZipWriter");
var odt = new zipWriter ();
odt.open(odtfile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE | PR_APPEND);

表 2 显示了一些可代替 Desk 的常用值。


表 2. 用来保存文件的常见目录
文件 描述
ProfD Firefox Profile 目录
Desk Desktop 目录(例如,Linux® 上的 ~/Desktop,Windows® 上的 C:\Documents 和 Settings\username\Desktop)
Home 操作系统根目录(例如,Linux 上的 /root,Windows 上的 C:\)
TmpD 操作系统临时目录

第二步是将所需的 OpenOffice 文档文件添加到这个归档文件。要记住,需要将每个文件添加到 图 1 所示的这个结构中的恰当位置。


清单 10. 将 OpenOffice 文档添加到归档文件
				
// locate file
var contentfile = em.getInstallLocation(eid).getItemFile(eid, oopath + "content.xml");
// add file to archive
odt.addEntryFile("content.xml", 
 Components.interfaces.nsIZipWriter.COMPRESSION_NONE,
 contentfile, false);

// create directory
odt.addEntryDirectory("META-INF", time * PR_USEC_PER_MSEC, false);
// locate file
var manifestfile = em.getInstallLocation(eid).getItemFile(eid, oopath + "manifest.xml");
// add file to specific directory in archive
odt.addEntryFile("META-INF/manifest.xml",
 Components.interfaces.nsIZipWriter.COMPRESSION_NONE, 
 manifestfile, false);

odt.addEntryDirectory("Thumbnails", time * PR_USEC_PER_MSEC, false);
var thumbfile = em.getInstallLocation(eid).getItemFile(eid, oopath + "thumbnail.png");
odt.addEntryFile("Thumbnails/thumbnail.png", 
 Components.interfaces.nsIZipWriter.COMPRESSION_NONE, 
 thumbfile, false);

var metafile = em.getInstallLocation(eid).getItemFile(eid, oopath + "meta.xml");
odt.addEntryFile("meta.xml", 
 Components.interfaces.nsIZipWriter.COMPRESSION_NONE, 
 metafile, false);

var mimetypefile = em.getInstallLocation(eid).getItemFile(eid, oopath + "mimetype");
odt.addEntryFile("mimetype", 
 Components.interfaces.nsIZipWriter.COMPRESSION_NONE, 
 mimetypefile, false);

var settingsfile = em.getInstallLocation(eid).getItemFile(eid, oopath + "settings.xml");
odt.addEntryFile("settings.xml", 
 Components.interfaces.nsIZipWriter.COMPRESSION_NONE, 
 settingsfile, false);

var stylesfile = em.getInstallLocation(eid).getItemFile(eid, oopath + "styles.xml");
odt.addEntryFile("styles.xml", 
 Components.interfaces.nsIZipWriter.COMPRESSION_NONE, 
 stylesfile, false);

// close the archive
odt.close();
            

现在新的 OpenOffice 文档已经创建完成,可以启动它了。

启动 OpenOffice 文档

启动可随意进行,因为新文档已经被保存到桌面上。新文档可以随时被手动打开,也可以将它用作其他过程的输入。

如果文件关联设置得恰当,那么下面示例中的代码将会自动打开 OpenOffice 中新创建的文档。


清单 11. 自动地启动 OpenOffice 文档
				
var ios = Components.classes["@mozilla.org/network/io-service;1"]
	   .getService(Components.interfaces.nsIIOService);
var odtURL = ios.newFileURI(odt);
location.href = odtURL.spec;
            

如果文件关联尚未设置,会出现类似如下所示的一个提示窗口。


图 4. 打开 OpenOffice 文档
时间:2009-08-04 09:40 来源:developerWorks 中国 作者:Stefanus Wiguna 原文链接

好文,顶一下
(1)
100%
文章真差,踩一下
(0)
0%
------分隔线----------------------------


把开源带在你的身边-精美linux小纪念品
无觅相关文章插件,快速提升流量