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 归档文件并将 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 中新创建的文档。
清单 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 文档