本文へジャンプ

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


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

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

  • 閉じる [x]

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

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

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


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

  • 閉じる [x]

JavaMailおよびXSLTを使ったe-zineの管理: 第2回

XMLとXSLTを使ってプレーン・テキストのニュースレターとHTMLのニュースレターの両方を自動的に作成する

Benoit Marchal (bmarchal@pineapplesoft.com), Consultant, Pineapplesoft
Photo of Benoit Marchal
Benoit Marchal氏は、ベルギーのナミュールを拠点にしたコンサルタントおよび著述家です。彼の著作には、XML by Example(Que社、邦訳: インプレス社「実例で学ぶXML」) と、Applied XML Solutions とがあります。Gamelanにコラムを寄せています。 Ben氏は、1998年にPineapplesoft Linkを設立したときに、e-zineの発行についてじかに学びました。www.marchal.com のサイトで、彼のe-zineを購読したり、彼の最新プロジェクトを詳しく見ることができます。

概要: このシリーズの最終回では、Benoît Marchalが、JavaとXMLを使ってe-mail発行にまつわる雑用を自動化する方法を紹介します。ここで紹介するXMLとXSLTの具体的な適用では、e-mailニュースレター (e-zine) 発行での適用を例に説明します。これはHTMLとプレーン・テキストのe-mailメッセージを出力するものです。再使用可能なコード例が5つ用意されており、そこには、JavaMailを使ってe-mailを送信するJavaプログラム、第1回で紹介されたDocBookの例をHTMLに変換するためのXSLTスタイル・シート、Java構成ハンドラー (SAXContentHandler の形式)、およびすべてを複数ステップの変換にまとめるJavaコードが含まれています。

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


このシリーズの第2回目では、JavaMailとXSLTを使ってe-zineの発行を自動化する方法を扱います。第1回では、DocBook XML文書をテキスト形式に変換し、e-mail発行の厳しい要件を満たす方法を学びました。そこでは3つのステップが関係していました。

  1. XSLTを使ってDocBookをテキスト・マークアップ言語へすぐに変換する
  2. カスタム・メードのJavaアプリケーションを使ってテキスト・マークアップ言語をプレーン・テキストへ直す
  3. さまざまなSAXフィルターを利用してテキストを整形する

このアプローチの利点の1つとして、複雑なプロセスをいくつかのステップに区分できることをあげられます。XSLTスタイル・シートを使うことで柔軟性が非常に高まります。DocBook以外のボキャブラリー向けに書かれた文書を発行すると決めている場合は、スタイル・シートを変更するだけで済むわけです。さらに、SAXフィルターを使って変換コンポーネントをモジュール化できるため、読みやすくなりますし、維持管理も簡単です。

第2回目は、JavaMail (標準Java言語e-mail API) を使って、どのようにこのプロセスをラップし、ネットワークでe-zineを送信するか説明します。また、プロセスではSAXイベント処理についてもう一度触れます。そして結論部分では、大規模なアプリケーションでXSLT処理をラップする方法を紹介します。第1回の図1には、すべての部品同士の相関関係が示されています。

図1. ソリューションのコンポーネントの相関関係
図1

JavaMail 101

先に進む前に、JavaMailについて思い起こしてみましょう。あなたがすでにJavaMailに精通しておられるなら、次のセクションにスキップしても構いません。

SMTPホスト

  • 初めてJavaMailを使う方は、SMTPホスト (SMTPリレー、メール・ホスト、または発信メール・サーバーとも言います) のところで混乱することがあります。
  • 概念は簡単なもので、あなたのISPが、e-mailを送信するためにe-mailクライアント (Eudora、Outlook、またはNetscape) で使うe-mailサーバーを用意しているということです。JavaMailは、このアプリケーションの中でe-mailクライアントを置き換えるため、e-mailサーバーにもアクセスする必要があるのです。
  • SMTPホストを判別するために、お使いのe-mailクライアントの構成を確認してください。念のため、ISPまたはシステム管理者にもお尋ねください。
  • 最後に警告を。企業ネットワークの中には、SMTPホストへ直接にアクセスできないものもあります。JavaMailは絶対にSMTPホストを必要とするため、そのようなケースでは、システム管理者を丸め込んで特別なアクセス権をもらうしかないでしょう。

E-mailは、これからも最もポピュラーなインターネット・アプリケーションの1つであり続けるでしょう。e-mailというと必ずEudora、Outlook、またはNetscapeといったe-mailクライアントと関連付けて考えてしまいがちですが、多くのアプリケーションには、e-mailを自動的に送信したり取り出したりする機能があります。最近、オンラインでものを購入したときのことを思い出してみてください。オーダーを完了して数分以内に、確認のe-mailが届けられたと思います。これは電子商店によって自動的に送信されたものです。これは人間が関係しておらず、Eudoraなどのe-mailクライアントを必要としません。

Javaアプリケーションでしばしばe-mailの送受信を行なう必要性を見て取ったSunは、e-mailサービス用の標準APIとしてJavaMailを開発しました。JavaMailを使うと、Javaアプリケーションでe-mailを送信したり、メールボックスを (e-mailクライアントを使わずに) 直接にチェックすることができます。JavaMailはSun JDKとは別にダウンロードする点にご注意ください (参考文献を参照)。

リスト1 にリストされているSendMessage.javaは、JavaMailを説明するための簡単なアプリケーションです。javax.mail およびjavax.mail.internet パッケージをインポートしている点にお気づきでしょう。

e-mailを送信するときの最初のステップは、Session.getDefaultInstance() を使って、Session オブジェクトを要求することです。Session.getDefaultInstance()Properties オブジェクトを持ち、これには、少なくともmail.smtp.host プロパティーが必ず含まれます。このプロパティーは、ご使用のSMTPホストを指していなければなりません。そうでないと、何も機能しません (サイドバーのSMTPホストを参照)。

次に、Message を作成し、そのいくつかのプロパティーをセットします。プロパティーとしては、送受信側のアドレス (注意点として、複数の受信側があっても構いませんが、送信側は1つだけです)、件名、日付、およびメッセージの本文などがあります。

最後のステップは、Transport.send() を使って、メッセージをネットワークで送信することです。SendMessage.javaでは、簡単なテキストe-mailが作成されるだけです。次のセクションでは、いわゆるマルチパートe-mailをどのように作成するか説明しましょう。



リスト1. SendMessage.java
                
package com.psol.xslist;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
public class SendMessage
{
public static final void main(String[] args)
{
try
{
if(args.length < 5)
{
System.out.println("java com.psol.xslist.SendMessage" +
" from@domain.com to@domain.com mailhost.domain.com" +
" subject \"mail content\"");
return;
}
Properties props = System.getProperties();
props.put("mail.smtp.host",args[2]);
Session session = Session.getDefaultInstance(props);
Message message = new MimeMessage(session);
InternetAddress from = new InternetAddress(args[0]);
InternetAddress to[] = InternetAddress.parse(args[1]);
message.setFrom(from);
message.setRecipients(Message.RecipientType.TO,to);
message.setSubject(args[3]);
message.setSentDate(new Date());
message.setText(args[4]);
Transport.send(message);
}
catch(MessagingException e)
{
System.err.println(e.getMessage());
}
}
}


e-mailは、インターネットe-mail規格で定義されている強力な概念です。この形式のe-mailは、メッセージの複数のコピーを、一般的にいくつかの異なる形式で含んでいます。そのため、e-mailクライアント側は最適なコピーを選択してユーザー側に提示することができます。

  • HTMLを利用できるe-mailクライアントではHTMLバージョンが使われ (そのバージョンがあれば)、テキスト・ベースのクライアントではテキスト・バージョンが使われます。この概念はe-zine発行に便利なものです。HTMLとテキストの両バージョンのe-zineを、multipart/alternative e-mailとして送信すれば、すべてのe-mailクライアントと互換性を保てます。
  • とにかく、これが理論です。実際には、ほとんどのテキスト・ベースのe-mailクライアントは、multipart/alternative が導入される前に作られたもので、テキストとHTMLの両バージョンをユーザー側に提示しています。残念なことに、HTMLの方は、ほとんどの読者にとって読めないゴミのようですね。ですから、賢明なe-zine発行者は、e-mailの中でテキスト本文がまず 表示されるようにしています。

マルチパートe-mailおよび構成ファイル

第1回で紹介したJavaMailとテキスト・フォーマッターで武装すれば、すぐにでもe-zineを送信できます。SendMessage.javaのsetText() を更新して、第1回で紹介したテキスト変換の結果を使うことができます。ただし、もっと良い方法があります。具体的に言うと、multipart/alternative e-mailを使うことができます (サイドバーのmultipart/alternative を参照)。

ここでは、リスト2 の中のconfig.xml のようなXML構成ファイルに、e-mail情報を保管することにします。このファイルの構造は次のとおりです。

  • cfg:email は構成ファイルのルートです。これには、SMTPホストに対して1つの属性smtp があります。テストの前に属性のパラメータを変更する必要があるため、リストの中の属性を太字にしておきました (サイドバーのSMTPホストを参照)。
  • cfg:header には、送受信側のアドレスが示されると同時に、属性としてのe-mail件名が示されます (それぞれは、fromto およびsubject です)。テストのときには、自分自身のe-mailアドレスを使ってください。
  • cfg:body は、source 属性の中で、ソースXML文書を示します。
  • cfg:textcfg:part は、cfg:body で囲まれていて、さまざまな本文部分を作成する方法を制御します。cfg:text は、第1回で紹介されたテキスト変換を使い、テキスト本文部分を作成するのに対し、cfg:body は、簡単なXSLTスタイル・シートに適用され、HTMLバージョンの本文を作成します。

このような要素はすべて、http://www.psol.com/xns/xslist/config 名前空間にあります。思い出していただきたいのですが、XML名前空間はURLの形式になっていますが、IDとして使われているに過ぎません。ですから、ブラウザーで名前空間を指定してみても、Webサイトを見つけることはできません。

最終的に、構成ファイルに受信側アドレスが1つだけ示されていることを確認してください。なぜ1つだけで良いかというと、ほとんどの人はメーリング・リストを配信するときに、TopicaやSparkLIST (参考文献を参照) などの特別なサーバーを経由しますが、そのサーバーが購読契約およびその解除を管理するからです。メーリング・リスト・サーバーにe-zineを送信すると、ただちにすべての読者へ配信されます。

このサンプル・コードを使ってみる前に、smtpfrom、およびto 属性を必ずあなた自身のものに変更してください。



リスト2. 仮メーリングのconfig.xml
                
<?xml version="1.0"?>
<cfg:email xmlns:cfg="http://www.psol.com/xns/xslist/config"
smtp="mailandnews.com">
<cfg:header from="username@mailandnews.com"
to="nobody@example.com"
subject="XSL -- First Step in Learning XML"/>
<cfg:body source="article.xml">
<cfg:text styleSheet="text.xsl" contentType="text/plain"/>
<cfg:part styleSheet="html.xsl" contentType="text/html"/>
</cfg:body>



構成ファイルの読み取り

構成ファイルの処理は、リスト3 のConfigHandler.javaで行われます。これはSAXDefaultHandler を継承していて、パーサーとのインターフェースをインプリメントしています。第1回で予告したように、このセクションではSAXイベント処理について検討します。SAXイベント処理に精通しておられるならば、ご自由にこのセクションを飛ばすことができます。

SAXはイベント・ベースのAPIなので、XMLファイルの処理を進めてゆくときに、パーサーは (AWTイベントに似た) イベントをアプリケーションへ送信します。アプリケーションでは、イベントを無視することもできますし、処理することもできます。ほとんどのイベント・ハンドラーでは、少なくとも次のイベントを処理します。

  • ・パーサーが開始タグを読み込むときに呼び出すstartElement()
  • ・パーサーが終了タグに達したときに呼び出すendElement()
  • ・パーサーが文字データを認識するときに呼び出すcharacters()。ConfigHandler.javaの特徴は、characters() イベントを無視することです。

SAXでは他のイベントも多数定義していますが、それらは主要なイベントではありません。他のSAXイベントの詳細は、参考文献を参照してください。

SAXを理解するために、XML文書は要素の階層だということを思い出してください。つまり、ツリー構造です。パーサーはこのツリーを読み取り、イベントを使ってアプリケーションへ通知します。パーサーは、startElement() を呼び出して、新しいブランチを見つけたことをアプリケーションへ通知します。endElement() は、現在のブランチの終了を示します。

SAXハンドラーを作成することの難しい点は、特定の要素 (cfg:body など) を処理するコードが、複数のイベント (startElement()endElement() など) に分けられることです。

さらに、パーサーはコンテキスト情報を戻してこないので、イベントを相互に対応させるのはアプリケーションになります。ConfigHandler.javaでは、構成内の読み取られた部分を知るために、state 変数を使います。

文書の作業を進めてゆくときに、ConfigHandler.javaはマルチパートのMessage を作成し、適切なスタイル・シートを適用して、異なるバージョンのメッセージ (テキストとHTML) を作成します。文書の最後にきたら、ConfigHandler.javaはメッセージを送信します。

異なるスタイル・シートを使うことにより、さまざまなバージョンの本文を好きなだけ作成できるので、このメカニズムは非常に柔軟なものだと言えるでしょう。3つ目のバージョンが (たとえば、WML (Wireless Markup Language) で) 欲しいという場合は、別のスタイル・シートを1つ指定し、構成ファイルをそれに適合させるだけでよいのです。


すべてを1つにまとめる作業

config.xml (リスト2) は、リスト4 で示されているhtml.xsl スタイル・シートを参照します。スタイル・シートhtml.xsl は、典型的なスタイル・シートの例で、第1回で紹介したarticle.xml をHTMLへ変換します。



リスト4. html.xslがarticle.xml (このシリーズの第1回のもの) をHTMLへ変換する
                
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of
select="article/articleinfo/title"/></title>
</head>
<xsl:apply-templates/>
</html>
</xsl:template>
<xsl:template match="article">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>
<xsl:template match="articleinfo/title">
<h1><xsl:apply-templates/></h1>
</xsl:template>
<xsl:template match="sect1/title">
<h2><xsl:apply-templates/></h2>
</xsl:template>
<xsl:template match="ulink">
<a href="{@url}"><xsl:apply-templates/></a>
</xsl:template>
<xsl:template match="emphasis">
<b><xsl:apply-templates/></b>
</xsl:template>
<xsl:template match="para">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="author">
<p>by <xsl:value-of select="firstname"/>
<xsl:text> </xsl:text>
<xsl:value-of select="surname"/></p>
</xsl:template>
</xsl:stylesheet>


最後の欠落している部分は、main() メソッドです。これは、リスト5 のXslList.javaにあります。ConfigHandler.javaは、e-mailの作成と送信を受け持つものですので、main() はとてもシンプルです。これは、SAXパーサーを作成し、ConfigHandler.javaをイベント・ハンドラーとして登録し、parse() を呼び出して構文解析を立ち上げます。

もちろん、パーサーが文書をデコードするときにはたくさんのことが生じます。(メッセージの作成や送信など) どのようなヘビー・デューティーな処理が行われるときも、パーサーはいつもConfigHandler.javaへイベントを送信します。parse() が戻ったときには、2つのスタイル・シートが適用されていて、e-mailが送信されているのです!



リスト5. XslList.java
                
package com.psol.xslist;
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
public class XsList
{
protected static final String
PARSER_NAME = "org.apache.xerces.parsers.SAXParser";
public static void main(String[] args)
{
try
{
if(args.length < 1)
{
System.out.println("java com.psol.xslist.XsList input.xml");
return;
}
ConfigHandler configHandler = new ConfigHandler();
XMLReader parser =
XMLReaderFactory.createXMLReader(PARSER_NAME);
parser.setFeature("http://xml.org/sax/features/namespaces",
true);
parser.setContentHandler(configHandler);
parser.parse(args[0]);
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
catch(SAXException e)
{
System.err.println(e.getMessage());
}
}
}



今度はご自分でどうぞ

私がこの記事を準備したとき、3つの目標がありました。まず、ブラウザーを使わないXMLアプリケーションを作成しようと思いました。ブラウザーでXMLを使うことは、アプレットでJavaを使うようなものです。この記事をお読みになり、便利なXMLではブラウザーを必要とはしないということを、はっきりと理解していただけたなら幸いです。

次に、XSLTとSAXイベント処理を組み合わせることが、それぞれの良さを合せたものよりもどれほどすばらしいか示したいと思いました。第1回では、SAXハンドラーに送られるマークアップを簡単にするため、どのようにXSLTを使うかを理解しました。

最後に、私は、ほとんどのプログラマーが例を学習することで理解を深めることを知っていましたので、完全なアプリケーションを提示したいと思いました。ついでながら、このアプローチを気に入っていただけたのであれば、拙著のApplied XML Solutions (参考文献を参照) も気に入っていただけるでしょう。ここには、別の例が8つ掲載されています。

それでは、今度はご自分で試してみてください。このアプリケーションは、e-zine発行という特定の作業で役に立ちますが、示されたXMLテクニック (XSLT、DocBook、SAXフィルター、JavaMailなど) は、e-zine発行だけに限定されているわけではありません。コードを学習し、ご自分の作業でどのように役立つかをご覧になってください。


参考文献

  • Dr. Ralph Wilson氏が、e-mailクライアントの概要について書いています。HTML e-mailのサポートについてもレポートしています。

  • メーリング・リスト・サーバーの契約を必要としているのであれば、2つのポピュラーなベンダー、Topica およびSparkLIST をお調べください。これらは、購読契約およびその解除を含めたリストを管理します。また、David Strom氏のWeb Informant もご覧ください。そこでは、メーリング・リスト・サービスの最新比較情報が載せられています。

  • JAXP (Java API for XML) は、SAX (XML構文解析) とTrAX (XSLT変換) を統合したものです。このサイトには、Stuart Halloway氏による、SAX tutorial があります。

  • SAXの詳細は、David Megginson氏のWebサイトをご覧ください。Megginson氏は、SAX APIの保守担当者です。

  • JavaMail は、e-mail用の標準Java APIです。(JDKとは別にダウンロードするものです。)

  • この2回にわたるシリーズの第1回目では、XMLからテキストへの変換について論じられています。また、このアプリケーションのアーキテクチャーについても述べられています。

  • この記事を気に入っていただけたのであれば、この記事の著者によるApplied XML Solutions をご覧になると、さらに良質な8つの例があります。

著者について

Photo of Benoit Marchal

Benoit Marchal氏は、ベルギーのナミュールを拠点にしたコンサルタントおよび著述家です。彼の著作には、XML by Example(Que社、邦訳: インプレス社「実例で学ぶXML」) と、Applied XML Solutions とがあります。Gamelanにコラムを寄せています。 Ben氏は、1998年にPineapplesoft Linkを設立したときに、e-zineの発行についてじかに学びました。www.marchal.com のサイトで、彼のe-zineを購読したり、彼の最新プロジェクトを詳しく見ることができます。

不正使用の報告のヘルプ

不正使用の報告

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


不正使用の報告のヘルプ

不正使用の報告

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


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, Java technology
ArticleID=243037
ArticleTitle=JavaMailおよびXSLTを使ったe-zineの管理: 第2回
publish-date=04012001
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 など)に対するお客様ご自身のタグを表示します。