本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

実用的なXML: コンテンツ・マネージメントにXSLTを使用する

XMの紹介: 手ごろなコンテンツ・マネージャー

Benoit Marchal (bmarchal@pineapplesoft.com), Consultant, Pineapplesoft
Benoit Marchal氏は、ベルギーのナミュールを拠点にしたコンサルタントおよび著述家です。彼の著作には、 XML by Example(Que社、邦訳: インプレス社「実例で学ぶXML」。間もなく第2版が出版される予定です)、 Applied XML Solutions および XML and the Enterprise があります。また、Gamelanのコラムや、developerWorks XML zoneのコラムWorking XML の著者でもあります。最新プロジェクトの詳細については、www.marchal.com をご覧ください。

概要: この記事は、「実用的なXML」の第1回です。このコラムは、成熟したXMLアプリケーションの進化を示すプロジェクト・コードと連携しています。このコラムで、ソフトウェア・コンサルタントである著者のBenoît Marchalは、XMLとXSLTを利用した、単純で手ごろなWeb出版用コンテンツ・マネージメント・ソリューションであるXM (XSLT Make) を紹介します。コード・サンプルでは、XMをプログラマー以外の人にとって使いやすくするための、XSLTのラッパーの開発を示しています。XMプロジェクト・コードはリンクで入手可能です。

日付:  2001年 7月 01日
レベル:  中級 この記事の原文:  英語
アクティビティー: 2620 ビュー
お気軽にご意見・ご感想をお寄せください: 


developerWorksの新規コラム「実用的なXML」の第1回へようこそ。このコラムの前提となる考えは、開発者にとって最上の学習方法はコードの研究であるということです。したがって、このコラムと並行して一連のXMLプロジェクトを開発し、何回かの記事でそのプロジェクトについて説明していきたいと思います。このような方法により、1回の記事向けに作り上げたシナリオでは扱えないような、より大規模で現実的なプロジェクトに取り組むことができます。これらのデモンストレーション・プロジェクトは、このコラムの連携サイトから、オープン・ソース・プロジェクトとして入手できます (参考文献を参照)。読者の皆さんや私が使用することによってこれらのプロジェクトが発展し、このコラムでその変更内容を報告できることを期待しています。

また、プロジェクトが誕生してから成熟するまでをたどれるということも、このような方法を用いることの興味深い特徴です。私の経験では、実際に機能するソリューションと同程度のこと (それ以上とは言わないまでも) をエラーから学ぶことができます。「実用的なXML」では実際のプロジェクトの開発をたどりますので、仮定の状況のみに基づく単発の記事に比べて、エラーによる袋小路について注意を促す機会が多くなります。進行中のオープン・ソース・プロジェクトとコラムをこのように組み合わせることにより、私たちの開発能力が向上することを期待しています。

XM: 手ごろなコンテンツ・マネージャー

最初に手がけるプロジェクトは、手ごろなWeb出版用ソリューションです。このプロジェクトの発想が浮かんだのは、200ページを超えるWebサイトの管理に四苦八苦しているときでした。小規模なサイトや大規模なサイトを管理するツールには、すばらしいものが存在していますが、その中間の規模のサイトについては、適切なソリューションが見付からなかったのです。

読者のサイトが10ページから20ページまでの規模であれば、HoTMetaL PRO、Dreamweaver、あるいはFrontPageなどのHTMLエディター (参考文献を参照) が最適です。しかし、これらのツールは、サイトが大きくなって、作業の重点が作成からコストの高い保守に移ると、あまり役に立たなくなってしまうのです。多くのHTMLエディターは、成長しつつあるサイトを保守するには次善の策にすぎません。そうしたエディターでは、たとえば、ナビゲーションを設計し直すだけのために、すべてのページを手作業で編集しなければなりません。20ページ程度のサイトを管理する場合には、「面倒くさい」といった程度で済みますが、もっと大きなサイトの場合には、大仕事になってしまいます。

これに対して、OpenMarket、Vignette、あるいはeContentなどの、ハイエンドの出版用ソリューションがあります (参考文献を参照)。これらは、巨大なコンテンツ・ベースを持つ大規模なサイトの管理には優れています。しかし (物事には常に「しかし」がつきものです)、入場料が高額すぎるため、過大な仕事を抱え込んでいるWebマスターたちのほとんどは、これらのシステムのどれかを使えたら、と指をくわえているのが実情ではないでしょうか。

それでは、その中間には何があるのでしょうか?自家製のソリューションです。多くのWebマスターたちは、スクリプト (JSP、ASP、またはPHP) とデータベースの組み合わせを利用して、成長を続けるサイトに対処してきました。この方法はうまく機能していますが、欠点がないわけではありません。1つには、サーバーに負担がかかるために、ページのロードが遅くなる可能性があります。また、スクリプト・ベースのWebサイトは、バグ、さらにはクラッシュを起こす危険が高くなります (もちろん、私自身のコードのことを言っているのであって、ユーザーの コードにバグの影響が及ぶわけではありません)。最後に、検索エンジンが、動的に生成されたサイトをインデックス化できない可能性があります。結局、スクリプトおよびデータベースはWebマスターにとって役に立つかもしれませんが、Webサイトの訪問者にとっては最適なソリューションとは程遠いものであることが分かりました。

XMLに関するコラムにふさわしいように、XMLおよびXSLTを基に構築された代替手段を提案します。DocBookまたはその他のXML言語で文書を作成し、それらを自動的にHTMLに変換することは簡単に行えます。ここでは自動的 という言葉が鍵になります。目標は、手作業による処理を減らし、サイトの保守をできるかぎり自動化することです。これを、小規模なWebマスタリングから業界規模のWebマスタリングへ移行する際の目標とします。

ただし、これは理論上のことです。実際には、これを気軽に試すには、読者がプログラマーであるほうが良いでしょう。XalanなどのXSLTプロセッサーは、まだ本当の意味で使いやすいとは言えません。Cocoon (参考文献を参照) のようなXML出版用フレームワークは存在しますが、これらもやはり開発者向けにできています。私のXM (XSLT Make) 作業の目標は、XSLTプロセッサーを親しみやすくすることです。最終的には、中規模のWebサイトを管理する、開発者以外の人もXMにアクセスできるようになることを期待しています。

私がこのプロジェクトを実用的なXML の最初のプロジェクトとして選択したのは、最近のdeveloperWorksの記事JavaMailおよびXSLTを使ったezineの管理 に関する読者のメールを読んで、出版用の使いやすいXSLTのアプリケーションに対する関心が依然として高いと思ったからです。


ロードマップ

図1はXMの機能のしくみを要約したものです。Webサイトを準備して公開するまでには、3つの段階があります。

  1. オーサリング: XMLエディターでコンテンツを作成するか、ワード・プロセッサーなどの非XMLソースからコンテンツを取得する。
  2. 公開: コンテンツをHTMLに変換する。
  3. 閲覧: コンテンツをブラウザーで表示する。

図1: XMによる3段階のWeb出版

XMが主に静的なHTMLページを生成するということに注意してください。目標とすることは、本来のパフォーマンスを犠牲にすることなく、WebマスターがWebサイトを管理しやすいようにすることです。パフォーマンスを向上させるために、動的に生成されるほとんどのWebサイトは、なんらかの種類のキャッシングを使用します。私は、静的HTMLページは、明らかに最高のキャッシング戦略であると信じています。

すでに述べたように、このプロジェクトは大変な特権を得ていますので、1回 (または2回) の記事ですべてを実現しようとは考えていません。実用的なXML のためのプロジェクトは、他の本格的な開発と同じように、数か月かけて成熟していきます。しかしここで、このセクションのまとめとして、すでに私が示したいくつかの課題や目標を指摘しておきたいと思います。もちろん、開発が進行するにつれてさらに増えると思います。

  • XSLTプロセッサーのための簡単に使えるラッピングを考案する (この記事で取り上げます)。
  • FTPを介してファイルをWebサーバーに自動的にアップロードする。
  • ファイルを管理し、それらのファイルをリンクする (1つの方法として、スタイル・シートにディレクトリーを読み取らせるというソリューションが考えられます)。
  • PDF (Adobe AcrobatによってサポートされるPortable Document Format)、SVG (イメージ用のScalable Vector Graphics)、RSS (Webポータル用のRich Site Summary) などの、複数の出版形式をサポートする。
  • 共同編集を行えるようにするために、Webサーバー自体でXMをホストする。

例によるコンテンツ・マネージメント

XMの最初のバージョンの主要な課題の1つは、プログラマー以外の人にも利用できるようにすることです。これは、単に親しみやすいボタンを使ってユーザー・インターフェースを整えればよいということではありません。私は、気の利いたボタンがたくさんあったところで、不親切なソリューションが親しみやすくなりはしないと思います。つまり、不親切なアプリケーションのままなのです。それよりもむしろ、私は理解しやすい操作モードを工夫しました。

最初に考え付いたのは、JavaMailおよびXSLTを使ったezineの管理 で構成ファイルを作成することでした。この記事を読んでいない方のために説明すると、構成ファイルは、適用するスタイル・シートおよび生成される結果を制御するファイルです。たとえば、リスト1 を参照してください。多くのバリエーションをテストしてみましたが、十分に親しみやすいものはできませんでした。


リスト1. rules.xml: 親しみやすい構成ファイルを作成する試みの1つ
                
<?xml version="1.0"?>
<rules version="1.0" xmlns="http://www.ananas.org/2001/xm/rules">
   <!-- apply the style sheet on XML files -->
   <rule extension="xml">
      <apply-stylesheet file="default.xsl"/>
      <copy from="$xslt" to="$target"/>
   </rule>
   <!-- copy GIF files -->
   <rule extension="gif">
      <copy from="$source" to="$target"/>
   </rule>
   <!-- create an XML file with the content of
        freebies/download, style it -->
   <rule directory="freebies/download">
      <ls dir="$current"/>
      <apply-stylesheet file="download.xsl"/>
      <copy from="$xslt" to="$target"/>
   </rule>
</rules>

やがて私は、規則や変数 ($source など) を備えた、このような構成ファイルは、本質的に使いにくいものであるということに気付きました。これはスクリプト言語に似ているのです。ご存じのとおり、スクリプト言語は初心者には向いていません。私は、より利用しやすいソリューションを考え付きました。最終的なWebサイトをまねて自動的に出力を作成するディレクトリーを、ユーザーに作成してもらうのです。私はこれを、例によるコンテンツ・マネージメント と呼ぶことにしました。なぜなら、ユーザーが実際に作成するものは、Webサイトがどう編成されるのかを示す例であるからです。XMはその他の構成を実際のWebサイトに作り替える必要はありません。


スケルトン・クラス

ここから先に進むには、ananas.org からプロジェクト・コードをダウンロードしてください。この先の記事を読む前に、このコードが必要になります。今月の記事で扱うコードはXMのスケルトンにすぎません。このコードは、最も基本的なことだけしか行いません。再帰的にソース・ディレクトリーをたどりながら、それぞれのXMLファイルにスタイル・シートを適用し、HTML形式でWebサイトを作成します。

現時点でのクラスは次のようになっています。

  • NotImplementedException は、私がいつもJava標準ライブラリーになくて困っている唯一のクラスです。
    開発中に、まだインプリメントされていないコードを呼び出そうとしたり、予期しない (したがってまた、インプリメントされていない) 状況に遭遇したりすることは珍しくありません。私は、自分がまだそうしたコードを書いていないということを明らかにすると、デバッグ作業に費やす時間を節約できることに気が付きました。
  • XMException。XMは、エラーを検出するとこの例外をthrowします。この例外には、TransformerExceptionSAXException のような、他の例外を組み込むことができます。
  • Resources は、使いやすさを考慮したものにすぎません。これにより、デフォルト・ロケールにあるリソースに高速でアクセスすることができます。
  • Messenger は、抽象エラー・メッセージおよび情報メッセージへのインターフェースです。現行バージョンのXMはコマンド行から実行されますが、私は、GUIまたはWebベースのインターフェースを構築するつもりです。すべてのメッセージにMessenger を経由させることにより、さまざまなインターフェースをサポートしやすくなります。
  • DefaultMessenger は、Messenger のデフォルトのインプリメンテーションであり、Writer に出力を書き出します。
  • DirectoryWalker は実際の処理を行います。これは一連のディレクトリーを再帰的にたどりながらスタイル・シートを適用します。
  • Console はXMのエントリー・ポイントです。その名前が示すように、これはコマンド行から使用されます。

Messenger

例外を無視すれば、現在のXMにおける最も便利なクラスはMessengerDirectoryWalker の2つです。リスト2 に示したMessenger は、ユーザーと通信するためのインターフェースを定義しています。このクラスはTrAXのErrorListener あるいはSAXのErrorHandler をモデルとしています。

  • error()fatal()、およびwarning() はエラーを報告するために使用されます。
  • progress() は、ユーザーに進捗状況を知らせるための進捗バーおよびその他のメカニズムをインプリメントするために使用できます。
  • info() はその他の情報を報告します。

XMは主として非対話式プロセスですので、私は、ユーザーに入力のためのプロンプトを出したり、その他の方法で入力を受け入れたりするためのメソッドを定義していません。


リスト2. Messenger.java: ユーザーに対するXMのインターフェース
                
package org.ananas.xm;
import java.io.File;
public interface Messager
{
   public void error(XMException e)
      throws XMException;
   public void fatal(XMException e)
      throws XMException;
   public void warning(XMException e)
      throws XMException;
   public void progress(File sourceFile,File resultFile)
      throws XMException;
   public void info(String msg)
      throws XMException;
   public void info(String pattern,Object[] arguments)
      throws XMException;
}


DirectoryWalker

リスト3 に示すDirectoryWalker は、基本的には、XMLファイルをソース・ディレクトリー (そのサブディレクトリー内のファイルも含めます) からターゲット・ディレクトリーにコピーするものです。ただし、1つの新しい工夫がしてあって、コピーする前にXMLファイルにスタイル・シートを適用するようになっています。


リスト3. DirectoryWalker.java: 工夫のあと
                
package org.ananas.xm;
import java.io.*;
import java.util.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import org.ananas.util.NotImplementedException;
public class DirectoryWalker
{
   protected Templates templates;
   protected long lastModified;
   protected String extension;
   protected Messager messager = null;
   public DirectoryWalker(File stylesheetFile,Messager messager)
      throws TransformerConfigurationException
   {
      lastModified = stylesheetFile.lastModified();
      templates = TransformerFactory.newInstance().
                     newTemplates(new StreamSource(stylesheetFile));
      extension = '.' + templates.getOutputProperties().
                           getProperty(OutputKeys.METHOD);
      this.messager = messager;
   }
   public void walk(String source,String target)
      throws IOException, XMException
   {
      walk(new File(source),new File(target));
   }
   protected void walk(File source,File target)
      throws IOException, XMException
   {
      if(source.isDirectory())
      {
         File[] files = source.listFiles(),
                dirs = new File[files.length],
                docs = new File[files.length];
         int idirs = 0,
             idocs = 0;
         for(int i = 0;i < files.length;i++)
         {
            if(files[i].isDirectory())
               dirs[idirs++] = files[i];
            else if(files[i].isFile())
               docs[idocs++] = files[i];
            else
               throw new NotImplementedException("Expecting file or directory");
         }
         if(!(target.exists() && target.isDirectory()))
            if(!target.mkdirs())
               messager.fatal(new XMException(
                  Resources.getString("cannotcreatedirectory"),
                  new Object[] {target.getAbsolutePath()}));
         for(int i = 0;i < idocs;i++)
         {
            String fname = docs[i].getName();
            int pos = fname.lastIndexOf('.');
            String extension = pos != -1 ? fname.substring(pos + 1) : "";
            if(extension.equals("xml"))
            {
               File result = style(docs[i],target);
               messager.progress(docs[i],result);
            }
            // else copy file
         }
         for(int i = 0;i < idirs;i++)
            walk(dirs[i],new File(target,dirs[i].getName()));
      }
      else
         messager.fatal(new XMException(
            Resources.getString("notdirectory"),
            new Object[] {source.getAbsolutePath()}));
   }
   protected File style(File sourceFile,File targetDir)
      throws XMException
   {
      try
      {
         String resultName = sourceFile.getName();
         int pos = resultName.lastIndexOf('.');
         if(pos != -1)
            resultName = resultName.substring(0,pos);
         resultName += extension;
         File resultFile = new File(targetDir,resultName);
         if(resultFile.exists())
         {
            if(resultFile.lastModified() >= sourceFile.lastModified() &&
               resultFile.lastModified() >= lastModified)
               return null;
         }
         Transformer transformer = templates.newTransformer();
         transformer.transform(new StreamSource(sourceFile),
                               new StreamResult(resultFile));
         return resultFile;
      }
      catch(TransformerException e)
      {
         throw new XMException(e);
      }
   }
}

walk() はディレクトリーをたどってスタイル・シートを適用します。まず最初にすべてのディレクトリーの内容をリストし、それをファイルとサブディレクトリーに分けます。次に、各ファイルのスタイルを設定し、サブディレクトリー用に再帰的に自分自身を呼び出します。

スタイル・シートの適用は、style() メソッドによって行われます。移植性を考慮して、DirectoryWalker はTrAX (Transformation API for XML) を使用してXSLTプロセッサーとインターフェースします。これまでのところ、私はXalan (参考文献を参照) を使用してコードをテストしました。


次回までの準備

XMコードは、すでに、ダウンロードして練習に使えるようになっています。エントリー・ポイントはorg.ananas.xm.Console クラスです。これは、2つのパラメーターだけを使用します。つまり、XMLファイルが入っているソース・ディレクトリーと、XMによって作成されるターゲット・ディレクトリーです。スタイル・シートは、rules.xsl という名前であり、現行ディレクトリーになければなりません。

現行バージョンは、大した機能を備えていませんので、ごく単純なWebサイト の公開にしか使用できません。次回の記事では、スタイル・シートからファイル・システムにアクセスできるようなメカニズムを追加する予定ですので、もっと面白いものになることと思います。


参考文献

  • このプロジェクトに関するすべてのコードは、ananas.org からダウンロードすることがでます。また、このプロジェクトに関連するニュースおよび発表のメーリング・リストに加入することができます。

  • XMは、XMLパーサーとしてXerces-J を使用し、XSLTプロセッサーとしてXalan を使用します。

  • 小規模なサイトの場合には、SoftQuad HoTMetaL PROMacromedia Dreamweaver、あるいはMicrosoft FrontPage などのHTMLエディターでも十分に役立ちます。

  • XMLおよびXSLTによる出版に関するdeveloperWorksのこの他の記事として、JavaMailおよびXSLTを使ったezineの管理 (第1回 および第2回) もあります。

  • Cocoon はオープン・ソースの出版用フレームワークであり、動的コード生成にきわめて多くを依存しています。

  • developerWorks XMLゾーン で、XMLに関するその他の参考文献を探してください。

著者について

Benoit Marchal

Benoit Marchal氏は、ベルギーのナミュールを拠点にしたコンサルタントおよび著述家です。彼の著作には、 XML by Example(Que社、邦訳: インプレス社「実例で学ぶXML」。間もなく第2版が出版される予定です)、 Applied XML Solutions および XML and the Enterprise があります。また、Gamelanのコラムや、developerWorks XML zoneのコラムWorking XML の著者でもあります。最新プロジェクトの詳細については、www.marchal.com をご覧ください。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML
ArticleID=242795
ArticleTitle=実用的なXML: コンテンツ・マネージメントにXSLTを使用する
publish-date=07012001
author1-email=bmarchal@pineapplesoft.com
author1-email-cc=dwxed@us.ibm.com

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。