邊做邊學 Web Application Toolkit 系列 6 - Web Application Toolkit for Template Driven Email 程式開發與解析
邊做邊學 Web Application Toolkit for Template Driven Email 程式開發與解析 |
其實筆者認為發送 E-Mail 程式碼並非是本 Toolkit 的重點,因為大家過去幾乎都有撰寫 E-Mail 發送程式經驗,所以這算不上什麼難事;反倒是 XML 套用 XSL 的程式設計才是本 Toolkit 重心,弄懂了 XSL 原理,自然整個程式邏輯都能輕易看懂。故本篇將從 XSL 設計與運用原理切入,再講解 Email.cs 及 EmailTemplate.cs 元件設計手法,相信您可以很快就貫通整個 Toolkit 程式脈絡。
一.XML 套用 XSL 觀念解析
在此我們先來練習 XML 如何套用 XSL 樣板樣,以下是步驟說明:
Step 1:建立 XML 檔
首先建立一個出版社的書籍銷售 Sales.xml 檔:
<?xml version="1.0" encoding="utf-8" ?>
<sales>
<summary>
<heading>愛書之友出版社</heading>
<subhead>全省銷售報告</subhead>
<description>台北,台中,高雄區域銷售報告</description>
</summary>
<data>
<region>
<name>台北</name>
<quarter number="1" books_sold="24000" />
<quarter number="2" books_sold="38600" />
<quarter number="3" books_sold="44030" />
<quarter number="4" books_sold="21000" />
</region>
<region>
<name>台中</name>
<quarter number="1" books_sold="11000" />
<quarter number="2" books_sold="16080" />
<quarter number="3" books_sold="25000" />
<quarter number="4" books_sold="29000" />
</region>
<region>
<name>高雄</name>
<quarter number="1" books_sold="27000" />
<quarter number="2" books_sold="31400" />
<quarter number="3" books_sold="40100" />
<quarter number="4" books_sold="30000" />
</region>
</data>
</sales>
Step 2:建立 XSL 樣板檔
接著建立 XSL 樣板檔,其主體結構如下:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>
…
</title>
<style>
…
</style>
</head>
</html>
<body>
…
</body>
</xsl:template>
</xsl:stylesheet>
其實 XSL 檔案與 .html 十分相似,裡面有 <html />、<head/> 或 <body/> 等區段的宣告,而使用方式也幾乎是一樣,剩下的工作就是把細部定義填滿,然後供 XML 檔套用即可,以下為完整的 Transform.xsl 定義:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>
<xsl:value-of select="//summary/heading"/>
</title>
<style>
th{
background-color:lightblue;
}
h1{
color:red;
}
</style>
</head>
<body>
<h1>
<xsl:value-of select="//summary/heading"/>
</h1>
<h2>
<xsl:value-of select="//summary/subhead"/>
</h2>
<p>
<xsl:value-of select="//summary/description"/>
</p>
<table border="1">
<tr>
<th>縣市\季</th>
<xsl:for-each select="//data/region[1]/quarter">
<th>
Q<xsl:value-of select="@number"/>
</th>
</xsl:for-each>
<th>Total</th>
</tr>
<xsl:for-each select="//data/region">
<tr>
<th style="text-align:left">
<xsl:value-of select="name"/>
</th>
<xsl:for-each select="quarter">
<td style="text-align:right">
<xsl:value-of select="format-number(@books_sold,'###,###')"/>
</td>
</xsl:for-each>
<td style="text-align:right;font-weight:bold;" >
<xsl:value-of select="format-number(sum(quarter/@books_sold),'###,###')"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
程式說明:
- XSL 從 XML 讀取資料是透過 <xsl:value-of select="//summary/heading"/> 這樣型式的語法,select 屬性指定欲讀取的節點名稱,就能自動載入節點資料。
- 而 <xsl:for-each select="//data/region[1]/quarter">…</xsl:for-each> 這種語法則是用迴圈的原理,反覆從 XML 節點讀取資料。
Step 3:XML 指定套用 XSL 樣板
XML 指定套用 XSL 樣板有兩種方式,一是靜態套用,二是動態套用,靜態套用是指在 XML 中明確指定 XSL 檔,而動態套用是在 Runtime 執行時,再以程式動態指定 XSL 進行套用。例如原本 Sales.xml 檔中第二行為刪除狀態,意思是不要加入,而在這個步驟中將加入以下宣告,完成 XSL 的靜態套用:
<?xml-stylesheet type="text/xsl" href="transform.xsl" ?>
Step 4:執行 XML
最後請以瀏覽器瀏覽 Sales.xml 檔,執行畫面如下圖。
圖1 XML 套用 XSL 樣板後之定義
解析 Email.cs 與 EmailTemplate.cs 程式
在瞭解較為困難的 XSL 原理之後,現在回過頭來看 Email.cs 與 EmailTemplate.cs 兩個程式,Email.cs 本身是負責純粹的電子郵件寄送的作業,而 EmailTemplate.cs 則是掌管 XSL 樣板檔的套用。
EmailTemplate.cs 程式解析
讓我們先從 EmailTemplate.cs 程式看起,其中最重要的就是產生電子郵件 body 內容的 GenerateEmailBody 方法,而此方法最核心的就是「動態套用 XSL」的語法,以下是重點語法:
public static string GenerateEmailBody(string templatePath, XNode xmlInputData)
{
string strHtml = string.Empty;
MemoryStream memoryStream = new MemoryStream();
StreamWriter writer = new StreamWriter(memoryStream, Encoding.UTF8);
XmlTextWriter htmlWriter = new XmlTextWriter(writer);
StreamReader streamReader = new StreamReader(memoryStream);
try
{
DebugLog("Starting Transformation for template: {0}...", templatePath);
DebugLog("Transformation Input Data:\n{0}", xmlInputData.ToString());
// 載入 XSL 定義
XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
xslCompiledTransform.Load(templatePath);
xslCompiledTransform.Transform(
xmlInputData.CreateNavigator(),
null,
htmlWriter);
memoryStream.Position = 0;
strHtml = streamReader.ReadToEnd();
}
catch (XsltException xsltException)
{
…
}
catch (Exception ex)
{
…
}
finally
{
…
}
DebugLog("Transformation Result:\n{0}", strHtml);
return strHtml;
}
程式說明:
- 載入與套用 XSL 的程式則是為 XslCompiledTransform 開始的 3 行程式,最後再以 strHtml 回傳套用 XSL 後的完整 HTML 內容,指定到電子郵件之中。
- DebugLog 方法的作用是寫入 Log 資訊到C:\TemplateDrivenEmail\code\CSharp\TemplateDrivenEmail.SimpleEmail\App_Data\Log\Transformations.log 的記錄檔之中。
Email.cs 程式解析
Email.cs 程式裡面只有三類方法,Send、CreateMailMessage 和 CreateInlineAttachment 方法,Send 是以多載方法型式撰寫,功用是發送電子郵件,而 CreateMailMessage 也是多載方法型式,用於建立電子郵件內容,至於 CreateInlineAttachment 方法則是處理電子郵件的 Attachment 附件。
例如 TemplateDrivenEmail.SimpleEmail 專案的 Default.aspx 程式,其中以 SendTemplateDrivenEmailAdvanced 方法發送套用複雜 XSL 樣板的電子郵件,其中發送郵件的程式只需要呼叫 Email.Send 方法即可,省去了重複撰寫發送 Mail 程式的不必要性,以下為程式碼:
C# 語法
protected void SendTemplateDrivenEmailAdvanced()
{
string advancedTemplatePath = Path.Combine(HttpRuntime.AppDomainAppPath, "App_Data/EmailTemplates/AdvancedTemplate.xsl");
XDocument xmlInputData = GenerateXmlData();
Email.Send(this.recipientTextBox.Text, this.subjectTextBox.Text, advancedTemplatePath, xmlInputData);
}
- VB 語法
Protected Sub SendTemplateDrivenEmailAdvanced()
Dim advancedTemplatePath = Path.Combine(HttpRuntime.AppDomainAppPath, "App_Data/EmailTemplates/AdvancedTemplate.xsl")
Dim xmlInputData = GenerateXmlData()
Email.Send(Me.recipientTextBox.Text, Me.subjectTextBox.Text, advancedTemplatePath, xmlInputData)
End Sub
三.VS 2008 對 XSL 測試與偵錯支援性
對 XSL 的程式開發,VS 2008 還供了 XSL 顯示與偵錯兩個功能,在開發過程中可提供方便的輔助,說明如下。
顯示 XSL Transformation 輸出結果
若欲透過 VS 2008 顯示 XSL Transformation 輸出結果,請開啓一個XSL檔,選擇 VS 2008的【XML】選單【顯示 XSLT 輸出】,系統會要求指定 XML 檔資料來源,然後在 VS 2008 就可直接顯示 XSL 套用後的畫面。
圖2 顯示 XSLT 輸出
圖3 XML 套用 XSLT 輸出結果XSL Transformation 偵錯
VS 2008 對 XSL 還支援偵錯功能,例如在 XSL 中設定中斷點(Breakpoint),選擇【XML】選單【偵錯XSLT】,便可像 C# 及 VB 程式進行逐步偵錯。
圖4 XSL 偵錯
四.結論
在介紹 XSL 的作用及原理後,您應能體會套用 XSL 樣板的優點,同時也更能理解將 Mail 發送程式獨立成元件的重複使用好處,您不妨試著將 Mail 元件及 XSL 樣板程式技巧引入您的專案,為程式帶來更好的美感與最佳化。