承接上講,本文深入剖析 XSLT 模板如何將資料庫結構 XML 轉換為 C#、Java、VB、HTML 等多種目標代碼。我們將逐行拆解核心模板 _csharphashtable.xslt,並展示 _HTML.xslt 如何實現單表/全庫雙模式輸出,最後說明熱插拔式模板擴展機制。
ASPX 頁面 GetXMLString 使用 XmlSerializer 將 DataBaseInfo → TableInfo → FieldInfo 三層物件樹序列化為 XML。關鍵細節:
[XmlType("Table")] 屬性將類別名 TableInfo 映射為 XML 元素 <Table>FieldInfo 的布林屬性(IsString 等)需提供 set 存取子產出的 XML 片段(以 Customers 表為例):
<Table>
<Name>Customers</Name>
<Fields>
<Field>
<Name>Address</Name>
<Remark>地址</Remark>
<FieldType>Char</FieldType>
<IsString>true</IsString>
<ValueTypeName>System.String</ValueTypeName>
<FieldWidth>60</FieldWidth>
<Nullable>true</Nullable>
<PrimaryKey>false</PrimaryKey>
</Field>
...
</Fields>
</Table>
_csharphashtable.xslt 逐節解析此模板生成以 Hashtable 內部儲存欄位值的 C# 實體類別。
<xsl:template match="/*">
<xsl:if test="name(.) != 'Table'">
<font color="red">本模板只能用於單表</font><br/>
</xsl:if>
<textarea ...> ... </textarea>
</xsl:template>
match="/*" 匹配 XML 根節點name(.) 檢查根元素名稱,非 Table 則輸出警告(XSLT 無 return,後續仍繼續輸出)<textarea> 包裹輸出,避免 HTML 特殊字元逸出麻煩<xsl:variable name="classname">
<xsl:value-of select="concat('DB2_' , Name )"/>
</xsl:variable>
concat() 為標準字串連接函數,參數 ≥ 2,支援 XPath 路徑與字面常數混合<xsl:text>
public static string[] FieldNames { get { return new string[] { </xsl:text>
<xsl:for-each select="Fields/Field">
<xsl:if test="position() > 1"><xsl:text>,</xsl:text></xsl:if>
<xsl:text>"</xsl:text><xsl:value-of select="Name"/><xsl:text>"</xsl:text>
</xsl:for-each>
<xsl:text> }; } }</xsl:text>
position() 返回當前節點在節點集中的 1-based 索引,用於控制逗號輸出xsl:text 保留空白字元(含換行),提升輸出代碼可讀性<xsl:for-each select="Fields/Field">
<xsl:variable name="remark">...</xsl:variable>
<!-- 註解與屬性宣告 -->
public <xsl:value-of select="concat(ValueTypeName, ' ', Name)"/> {
get { return <xsl:choose>
<xsl:when test="ValueTypeName='System.Byte[]'">
(<xsl:value-of select="ValueTypeName"/>) myValues["<xsl:value-of select="Name"/>"]
</xsl:when>
<xsl:otherwise>
Convert.To<xsl:value-of select="substring-after(ValueTypeName, '.')"/>(myValues["<xsl:value-of select="Name"/>"])
</xsl:otherwise>
</xsl:choose>; }
set { myValues["<xsl:value-of select="Name"/>"] = value; }
}
</xsl:for-each>
xsl:choose/when/otherwise 類似 switch/case/default,但 when 可寫任意 XPath 條件,更靈活substring-after(ValueTypeName, '.') 從 System.String 取得 String,構造 Convert.ToString(...)Convert.ToByte[] 不存在問題_HTML.xslt 單表/全庫雙模式此模板展示命名模板重用技巧:
<xsl:template match="/*">
<xsl:for-each select="//Table"> <!-- XPath // 選取所有後代 Table -->
<xsl:call-template name="table"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="table">
<div>...表頭資訊...</div>
<table>
<tr bgcolor="#eeee99">...標題列...</tr>
<xsl:for-each select="Fields/Field">
<xsl:sort select="Name"/> <!-- 依欄位名排序 -->
<tr>
<xsl:attribute name="bgcolor">
<xsl:if test="position() mod 2 = 0">#eeeeee</xsl:if>
</xsl:attribute>
<td><font><xsl:if test="PrimaryKey='true'"><xsl:attribute name="color">red</xsl:attribute></xsl:if><xsl:value-of select="Name"/></font></td>
...
</tr>
</xsl:for-each>
</table>
</xsl:template>
設計精華:
match="/*" 遍歷所有 //Table,呼叫子模板 table → 單一模板檔支援單表與全庫輸出xsl:attribute 動態生成屬性:隔行變色(position() mod 2)、主鍵紅字xsl:sort 確保輸出穩定順序// cmdCreate_Click 事件處理核心
DataBaseInfo info = GetInfo();
string xml = (cboTable.SelectedIndex == 0) ? GetXMLString(info) : GetXMLString(selectedTable);
if (cboXSLT.SelectedIndex <= 0) {
// 直接顯示 XML
html = "<textarea>" + xml + "</textarea>";
} else {
// XSLT 轉換
XslTransform transform = new XslTransform();
transform.Load(Server.MapPath(cboXSLT.SelectedValue) + ".xslt");
StringWriter writer = new StringWriter();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
transform.Transform(doc, null, writer, null);
html = writer.ToString();
}
lblResult.Text = "<b>共生成 " + html.Length + " 個字元</b><br/>" + html;
XslTransform 為 .NET Framework 1.x/2.0 核心轉換類(.NET Core 建議用 XslCompiledTransform)Load 可接受檔案路徑、URL、XmlReaderStringWriter,最終取得 HTML 字串直接注入 Label_*.xslt),置於應用程式目錄RefreshSystem 啟動時掃描目錄 Directory.GetFiles("_*.xslt") 填充下拉選單本專案展示了資料驅動代碼生成的經典架構:
資料庫結構 → XML 序列化 → XSLT 模板 → 目標代碼 (C#/Java/HTML/SQL...)
優勢: 核心代碼極少(< 500 行)、模板靈活可擴展、跨平台(XSLT 為 W3C 標準,易移植至 Java/PHP)。
挑戰: XSLT 模板編寫門檻高(需同時掌握輸入 XML 結構、輸出代碼語法、XPath/XSLT 語法)、除錯工具相對匱乏。
建議:嘗試為專案新增 _python.xslt 或 _sqlproc.xslt,體驗模板驅動開發的擴展威力。下一階段我們將進入 C# 圖形開發領域,探索完全不同的技術維度。