DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 用JavaMail和XSLT管理e-zine(2)
用JavaMail和XSLT管理e-zine(2)
編輯:XML詳解     

這是有關如何使用 JavaMail 和 XSLT 來實現 e-zine 發布自動化的文章系列的第二部分。在 第 1 部分中,您已經學到了如何將 DocBook XML 文檔轉換成滿足電子郵件發布苛刻需求的文本格式。這需要三個步驟:

  使用 XSLT 將 DocBook 轉換成臨時的文本標記語言

  使用定制的 Java 應用將文本標記語言重新格式化成純文本

  在各種 SAX 過濾器的幫助下整理文本

  這種方法的一大好處是:將復雜的過程拆分成幾個獨立的步驟。XSLT 樣式表為您帶來極大的靈活性: 如果要發布的文檔不用 DocBook、而用其它詞匯表編寫,則只更改樣式表即可。而且,SAX 過濾器還幫助使轉換組件模塊化,這就使組件更易讀和更易維護。

  在第 2 部分中,我將演示如何用 JavaMail,這個標准 Java 語言電子郵件 API,來通過網絡發送 e-zine,從而完成這個過程。在該過程中,我將重述 SAX 事件處理。這個結論演示了如何在大型應用中集成 XSLT 處理。第 1 部分中的圖 1 演示了組件是如何協同工作的。

  圖 1. 解決方案中的組件如何交互

用JavaMail和XSLT管理e-zine(2)

  JavaMail 101

  在繼續進行之前,我們先回顧 JavaMail。如果您已熟悉 JavaMail,則可以 跳到下一節。

  電子郵件始終是最流行的因特網應用程序之一。雖然我們往往將電子郵件與 Eudora、Outlook 或 Netscape 這樣的電子郵件客戶機聯系起來,但是很多應用程序可以自動發送或檢索電子郵件。回想上一次的聯機購物。在完成訂單後的幾分鐘之內,您很可能會受到一封確認電子郵件。它是由電子商店自動發送的。沒有人工參與,並且不需要如 Eudora 這樣的電子郵件客戶機。

認識到 Java 應用程序經常需要發送或接受電子郵件,Sun 開發了 JavaMail 作為標准 API,以用於電子郵件服務。通過 JavaMail,Java 應用程序可以直接發送電子郵件或查看郵箱(無需通過電子郵件客戶機)。請注意,JavaMail 獨立於 Sun JDK 單獨下載(請參閱 參考資料)。

  清單 1 中的 SendMessage.java 清單是一個演示 JavaMail 的簡單應用程序。請注意,它導入 javax.mail 和 Javax.mail.internet 包。

  要發送電子郵件,第一步是通過 Session.getDefaultInstance() 請求 Session 對象。 Session.getDefaultInstance() 需要一個 PropertIEs 對象,該對象必須至少包含 mail.smtp.host 特性。這個特性必須指向您的 SMTP 主機,否則將無法工作(請參閱側欄 SMTP 主機)。

  下一步是創建一個 Message 並設置其各種特性,包括發件人和收件人(請注意,可以有多個收件人,但只能有一個發件人)地址、主題、日期和消息主題。

  最後一步是使用 Transport.send() 通過網絡發送消息。SendMessage.Java 只創建一個簡單的文本電子郵件。下一節,我將講述如何創建所謂的多部分電子郵件。

  清單 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());
   }
  }
}

多部分電子郵件和配置文件

  有了 JavaMail 和 第 1 部分中介紹的文本格式化器,就可以發送 e-zine 了。可以更新 SendMessage.Java 中的 setText() ,以使用第 1 部分中介紹的文本變換結果,然而,還可以做得更好。特別是,還可以使用 多部分/備用 電子郵件(請參閱側欄 多部分/備用)。

  我選擇將電子郵件信息存儲在 XML 配置文件(如 清單 2 中的 config.XML )中。該文件的結構如下所述:

  cfg:email 是配置文件的根。它有一個屬性 smtp ,指明 SMTP 主機。在測試之前,必須更改這個參數,因此,我在清單中用粗體標記這個屬性(回想一下側欄 SMTP 主機)。

  cfg:header 包含三個屬性:發件人和收件人地址以及電子郵件主題(分別是 from 、 to 和 subject )。在測試時,請確保使用您自己的電子郵件地址。

  cfg:body 指向其 source 屬性中的源 XML 文檔。

  cfg:body 中還包括 cfg:text 和 cfg:part ,它們控制如何創建不同的消息主體部分。 cfg:text 使用第 1 部分中介紹的文本轉換來創建文本主體,而 cfg:body 則應用簡單的 XSLT 樣式表來創建主體的 Html 版本。

  所有這些元素都位於 http://www.psol.com/xns/xslist/config 名稱空間中。請記住,雖然 XML 名稱空間的形式是 URL,但它只用作標識。換句話說,如果將浏覽器指向那個名稱空間,將找不到任何網站。

  最後請注意,該配置文件只包含一個收件人的地址。那是因為大多數人都通過特殊的服務器(如 Topica 或 SparkLIST,請參閱 參考資料)分發郵遞列表,這些服務器將管理有關訂閱和取消訂閱的事項。將 e-zine 發送到郵遞列表服務器將把 e-zine 發往所有訂戶。

  請確保在嘗試這段樣本代碼之前將 smtp 、 from 和 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>
</cfg:email>
   

  讀取配置文件

  處理配置文件的工作由 清單 3 中的 ConfigHandler.Java 執行。它繼承 SAX DefaultHandler ,並用語法分析器實現接口。正如 第 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 發送消息。

  這種機制被證明是很靈活的,因為您可以通過使用不同的樣式表來創建任意多的消息主體版本。如果還想使用第三種版本,(比如 WML(無線標記語言)),只需再提供一個樣式表並相應改寫配置文件即可。

  集成在一起

  清單 2 中的 config.xml 引用 清單 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 負責創建和發送電子郵件,所以, main() 非常簡單:它創建一個 SAX 語法分析器,將 ConfigHandler.Java 注冊為事件處理器,然後通過調用 parse() 開始語法分析。

  當然,在語法分析器分析文檔語法時發生很多事。語法分析器一直向 ConfigHandler.java 發送事件,很多重要的處理(例如創建和發送消息)在 ConfigHandler.Java 中進行。當 parse() 返回時,已經應用了兩個樣式表並且電子郵件已經被發送。

  清單 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());
   }
  }
}

  現在該您了

  我准備本文的目的有三個。我想構建一個不使用浏覽器的 XML 應用。我認為,在浏覽器中使用 XML 與使用 Java 進行小應用程序設計的意義沒什麼不同。希望本文清楚地表明了這樣一個觀點:有用的 XML 不需要浏覽器。

  我還想演示 XSLT 和 SAX 事件處理的組合為何比只使用某一技術本身要好。在 第 1 部分中,您已經看到了如何使用 XSLT 來簡化為 SAX 處理器提供的標記。

  最後,因為我知道大多數程序員都是通過研究示例來學習更多知識的,所以,我為您演示了一個完整的應用。順便提一句,如果您喜歡這種方式,那麼,您還會喜歡我寫的 ApplIEd XML Solutions一書(請參閱 參考資源),這本書包含了其它八個示例。

  現在該您了。本文中的應用只用於 e-zine 發布這個特定領域,但是它所演示的 XML 技術(XSLT、DocBook、SAX 過濾器、JavaMail 以及其它技術)並不限於 e-zine 發布。請研究代碼,看看它如何在您的領域內幫助您。




 

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved