レベル: 初級 Stefanus Wiguna , Advisory Software Engineer, IBM
2009年 7月 07日 Mozilla の XPCOM (Cross Platform Component Object Model) フレームワークを利用すると、既存の XML コンテンツを OpenOffice 文書へと動的にエクスポートすることができます。このプロセスは、XSLT などの変換メカニズムでサポートされている他の任意タイプのコンテンツの場合も同様に機能します。この記事では、サーバー・サイドのソリューションに代わる、移植性とコスト効果の高いソリューションについて学びます。
はじめに
OpenOffice は、高価な商用オフィス・ソフトウェア・スイートに代わるオープンソースのオフィス・ソフトウェア・スイートとしてよく使われるようになっています (しかも、無料です)。ただしコンテンツの作成や、既存のコンテンツを OpenOffice へとエクスポートする作業は、適切なツールがないと非常に面倒です。
通常、OpenOffice 文書を動的に作成したり、既存のコンテンツを OpenOffice 文書へと動的にエクスポートしたりするためには、以下の作業を行う必要があります。
- サーバー上で実行されている Web アプリケーションによって、対象そのコンテンツを ODF (OpenDocument Format) に変換します。
- 変換されたコンテンツを OpenOffice 文書アーカイブに圧縮します。
- そのファイルを保存するか、あるいはユーザーに提供します。
しかし、サーバー・サイドのアプリケーションを利用できない場合にはどうするのでしょう。あるいは、このプロセスをクライアントに移すことで単純にサーバー負荷を最小にしたい場合にはどうするのでしょう。
 | | この記事では、XPCOM、Firefox 拡張機能、OpenOffice、OpenDocument Format、XSLT についての詳細な説明は省略します。これらの話題に関する詳細は「参考文献」を参照してください。 |
|
この記事では、Mozilla の XPCOM (Cross Platform Component Object Model) フレームワークを使ってアプリケーションを迅速に開発する方法を学びます。また、例を通して、Firefox 拡張機能の中で XPCOM コンポーネントを使って、既存の XML コンテンツを OpenOffice 文書へと動的にエクスポートする方法を説明します。この方法の使い道は XML のエクスポートのみに限定されているわけではありません。他のタイプのコンテンツも、そのコンテンツが (XSLT (Extensible Stylesheet Language Transformations) などの) 変換メカニズムでサポートされている限り、同じ方法で処理することができます。
実際にコンテンツを動的に OpenOffice へとエクスポートする前に、次のセクションで OpenOffice 文書を作成するための要件について説明します。
OpenOffice 文書
基本的に、OpenOffice 文書は圧縮されたファイルであり、ある文書のさまざまな部分 (コンテンツとスタイル、マニフェスト、サムネイルなど) を記述する一連の XML ファイルで構成されています。
図 1 は、OpenOffice テキスト文書 (.odt) を取得して .zip 拡張子を付けてリネームし、それを解凍した場合のファイル構造を示しています。
図 1. OpenOffice 文書の構造
表 1 はいくつかのファイルを簡単に説明したものです。
表 1. OpenOffice 文書のファイル
| ファイル | 説明 |
|---|
| content.xml | その文書の実際のコンテンツを含んでいます。 |
|---|
| meta.xml | shi a shi作成日や著者などのメタデータ情報を含んでいます。 | | styles.xml | 段落や文字などのフォーマット・スタイルを定義します。 |
新しい OpenOffice 文書を作成する上で最も容易で最も安全な方法は、既存の文書を編集する方法です。この記事では、文書の実際のコンテンツが保存されている content.xml のみを更新します。content.xml 自体は図 2 のようなものです。
図 2. OpenOffice 文書の content.xml
この記事の例では、実際のコンテンツの前にあるセクションを content head と呼ぶことにし、実際のコンテンツの後にあるセクションを content tail と呼ぶことにします。実際のコンテンツ自体は content body です。新しい OpenOffice 文書を作成する際には、必ずこれらのセクションを使います。
開発環境を準備する
OpenOffice へとエクスポートするためには、Firefox 拡張機能の開発環境の中でいくつかのことをする必要があります。ここでは既存の OpenOffice 文書を編集して新しい OpenOffice 文書を作成するため、次のことをする必要があります。
- 図 1 の中にあるすべてのファイルを Firefox 拡張機能のパッケージの中に含めます。これらのファイルを使って新しい OpenOffice 文書を作成します。
- これらのファイルを Firefox 拡張機能のクローム・フォルダーの外に保存します。こうすれば、拡張機能のパッケージング中にファイルが圧縮されることがなく、後でファイルを容易に取得できるようになります。
Firefox 拡張機能の内部にどのような構造でファイルが保存されているのかを示したものが下記の図です。
図 3. Firefox 拡張機能の構造の中での OpenOffice 文書ファイル
OpenOffice 文書のファイルはすべて同じフォルダーに保存することができます。OpenOffice 文書を作成する際には、アーカイブの中の適切な場所に各ファイルを置きます。xml2odt.xsl は既存のコンテンツを ODF に変換するために使うカスタムのスタイルシート・ファイルです。
次のステップでは、いくつかの変数と定数を設定します。これらの変数と定数は、OpenOffice 文書を生成するプロセス全体で行われるファイル操作 (ファイルの検索や取得など) で使われます。リスト 1 はその一例です。変数と定数の設定には XPCOM の nsIExtensionManager インターフェースを使用します。
リスト 1. 変数と定数を設定する
var eid = "export2OO"; // extension id
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
var oopath = "export/oo/"; // path to the OpenOffice document files
var ooxslt = "xml2odt.xsl";
const PR_WRONLY = 0x02;
const PR_RDWR = 0x04;
const PR_CREATE_FILE = 0x08;
const PR_APPEND = 0x10;
const PR_TRUNCATE = 0x20;
const PR_USEC_PER_MSEC = 1000;
const time = Date.now();
|
この記事のコードはすべて、Firefox 拡張機能がアクセスできる場所でありさえすれば、任意の場所に置くことができます。通常は、クローム・フォルダーの中にある JavaScript ファイル (.js) の中にコードを保存し、その JavaScript ファイルを Firefox 拡張機能のメインの XUL ファイルの中に含めます (リスト 2)。
リスト 2. Firefox 拡張機能の中にコードを含める
<overlay id="export2OO"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript;version=1.7"
src="chrome://export2OO/content/export.js" />
|
これで開発環境が準備できたので、次のセクションでは実際に文書を作成します。
OpenOffice 文書をプログラムで作成する
既存のコンテンツを OpenOffice 文書へと動的にエクスポートするための主なタスクには、次の 3 つがあります。
- 既存のコンテンツを OpenDocument フォーマットに変換する
- その新しいコンテンツを使って新しい OpenOffice 文書を作成する
- 新しく作成された OpenOffice 文書を自動的に起動する
既存のコンテンツを OpenDocument フォーマットに変換する
XSLT (Extensible Stylesheet Language Transformations) を使用すると、既存のコンテンツを容易に ODF に変換することができます。例えばリスト 3 は、XML フォーマットでのコンテンツの一部を示しています。
リスト 3. XML で表現したコンテンツ
<h1>This is Heading 1</h1>
<h3>This is Heading 3</h3>
|
リスト 4 は同じコンテンツをODF で表現したものです。
リスト 4. ODF で表現したコンテンツ
<text:h xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
text:style="Heading1" text:outline-level="1">
This is Heading 1
</text:h>
<text:h xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
text:style="Heading3" text:outline-level="3">
This is Heading 3
</text:h>
|
ODF 仕様には、スタイルの定義とフォーマットに関するあらゆる情報が提供されています (「参考文献」を参照)。スタイルシート・ファイルが用意できると、Firefox 拡張機能の環境の中で変換を実行することができます。そこで、拡張機能マネージャーを使用して、変換に使用するスタイルシート・ファイルを見つけます。リスト 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 を作成するためには、適切な content head と content tail を含める必要があります (図 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 アーカイブを作成し、その OpenOffice アーカイブに content.xml と他の必須ファイルを追加します。この例では、そのために XPCOM の nsIZipWriter インターフェースを使っています。
最初のステップとして、アーカイブ・ファイルを作成し、それをユーザーのマシンに保存します。下記の例では、新しいファイルをデスクトップ領域に保存します (リスト 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 のプロファイル・ディレクトリー |
|---|
| Desk | デスクトップ・ディレクトリー (Linux® での ~/Desktop や Windows® での C:\Documents and Settings\username\デスクトップなど) | | Home | オペレーティング・システムのルート・ディレクトリー (Linux の /root や Windows の C:\ など) | | TmpD | オペレーティング・システムの一時ディレクトリー |
第 2 のステップとして、必要な 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 文書を開く
これで、すべて完了です。
Firefox 拡張機能をビルドしてインストールすると、この記事のコードによって「OpenOffice へのエクスポート」機能をクライアント上で実現することができます。
まとめ
XPCOM のリッチなライブラリーによって、アプリケーションの開発を迅速に行えるようになり、それまではサーバー・サイドでしかできなかったことをクライアント・サイドで行えるようになります。これにより、サーバー・サイドのソリューションに代わる、移植性とコスト効果の高いソリューションを得ることができます。
参考文献 学ぶために
製品や技術を入手するために
- OpenOffice と拡張機能をダウンロードしてください。
- XPCOM のサイトは XPCOM に関連するすべての情報を入手できる中心的な場です。
- Firefox アドオンによって Firefox を拡張することができ、ブラウザーでのエクスペリエンスをパーソナライズすることができます。
- 皆さんの次期オープンソース開発プロジェクトを IBM ソフトウェアの試用版を使って革新してください。ダウンロード、あるいは DVD で入手することができます。
- IBM 製品の試用版をダウンロードするか、あるいはオンラインで IBM SOA Sandbox を試し、DB2®、Lotus®、Rational®、Tivoli®、WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。
議論するために
著者について  | 
|  | Stefanus Wiguna はノースキャロライナ州 Research Triangle Park にある IBM Software Group のアドバイザリー・ソフトウェア・エンジニアです。彼は Principal Certified Lotus Professional であり、Lotus、Web 2.0、Java 技術を使ったソリューション開発と統合に 10 年以上の経験があります。 |
記事の評価
|