程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#發現之旅第二講 C#-XSLT開發

C#發現之旅第二講 C#-XSLT開發

編輯:關於C#

為了讓大家更深入的了解和使用C#,我們開始這一系列的主題為“C#發現之旅 ”的技術講座。考慮到各位大多是進行WEB數據庫開發的,而所謂發現就是發現我們所 不熟悉的領域,因此本系列講座內容將是C#在WEB數據庫開發以外的應用。目前規劃的主要內 容是圖形開發和XML開發,並計劃編排了多個課程。在未來的C#發現之旅中,我們按照由淺入 深,循序漸進的步驟,一起探索和發現C#的其他未知的領域,更深入的理解和掌握使用C#進 行軟件開發,拓寬我們的視野,增強我們的軟件開發綜合能力。

本課程說明

本課程介紹XPath和XSLT的基本概念,並介紹了如何在C#中使用這些技術。

XPath介紹

XPath是從XML基礎規范上派生的技術,專門用於快速檢索和查詢XML文檔,使用方便 ,功能強大,XPath也是XSLT技術的基礎。

XPath是W3C國際標准組織定義的用於在單 個XML文檔中快速檢索和定位XML文檔節點的規范,它也是跨平台的,若一些軟件支持XPath, 則必然是支持標准的XPath語法。因此無論是JAVA還是C#都是支持相同語法的XPath。

我們理解XPath時可以參考文件目錄結構FilePath,在Windows資源管理器左邊的文件目錄樹 狀列表中,可以看到各種文件對象,包括磁盤根目錄,各級文件目錄等等,它們共同構成了 一個樹狀結構,我們選擇對象時既可以在這個樹狀結構中一個個查找,也可以指定路徑名來 進行快速定位,文件系統的路徑名采用斜槓號來分隔各個目錄層次的目錄名。比如在這個示 意圖中,我們選中的目錄,可以使用路徑名”c:\documents and settings\袁永福 ”來快速定位。

而XML文檔中也是這種樹狀層次結構,因此我們也可以套用這種 文件路徑名的概念到XML文檔中,於是形成了XPath路徑。我們處理XML文檔時可以一層層查找 所需的XML節點,也可以指定XPath路徑字符串來快速定位XML節點。在XPath路徑中,我們使 用反斜槓符號來分隔各個層次的XML元素的名稱。

在文件目錄系統中,我們可以可以 使用絕對路徑名,也可以使用相對路徑名,我們可以使用一個點號表示當前目錄,使用兩個 點表示父目錄。在XPath中我們也套用了類似的概念,我們從XML文檔根節點出發而指定的 XPath路徑為絕對路徑,從某個XML節點開始轉到其它節點所經過的路徑為相對路徑,我們也 使用一個點表示當前節點,也使用兩個點來表示父節點。其實我們可以將絕對路徑看成從根 節點出發的相對路徑。

在這個示意圖中,第一個選中的節點可以使用XPath路徑 “Table/Record/Country”來快速定位。

在文件目錄系統中,同一個目錄 下面不能有相同名稱的對象,因此相對路徑名和絕對路徑名都能准確的定位到一個目錄上, 而在XML文檔中,同一個XML節點下可以存在多個具有相同名稱的子節點,因此XPath路徑可能 無法唯一的確定一個XML節點。此時XPath采用了內嵌條件判斷語句的方法來解決這個問題。 XPath路徑字符串中可以使用一對方括號來包含一個邏輯表達式,在這個表達式中可以使用字 符串判斷,數學四則運算,邏輯判斷和一些預定義函數,而且XPath路徑中每個層次都能包含 表格式,因此XPath的邏輯判斷的功能是非常強大的。

在示意圖中,我們使用XPath路 徑”Table/Record[CustomerID=’ANATR’]/Phone”來快速定位第二 個節點,此處使用了一段方括弧包含了一個邏輯表達式。表示查找某個節點,該節點下的 CustoemrID子節點的文本值等於 “ANATR”。

XPath是一種國際標准,但 在微軟的.NET框架當然支持這個國際標准。我們可以使用.NET類庫中的 System.Xml.Xsl.XslTransform類型來執行XSLT轉換。這個類型除了支持標准的XPath外,還 進行一些擴展,主要是能擴展使用開發者自己定義的函數。

使用XPath,我們可以很 方便的搜索XML文檔中的任何部分,因此具有很好的數據檢索分析功能,近期業界興起的半結 構化文檔技術大多就是以XPath為基礎的。

由於XPath技術是相當強的,而且是國際標 准,跨平台的,因此大家有時間好好學習使用它。對於XPath的詳細語法可訪問網站 http://www.w3.org/TR/xpath ,若大家安裝了MSDN2003版,也可參考 MSDN Library/XML Web Services/XML核心/SDK 文檔/MSXML4.0 SDK/XPath Reference。這些電子文檔全是英文 ,大家也可以購買一些專門講述XML技術的中文書籍看看。

XSLT介紹

XSLT是一種將XML文檔轉換為其他文本文檔的語言,是建立在XML和XPath之上的國際 標准,內容比較多,功能強大。

對於編程人員來說,XSLT可以看作以前序遍歷的方式 專門處理XML樹狀結構的標記語言。以前編程根據XML文檔輸出純文本數據時需要寫代碼以前 序遍歷方式的方式遍歷XML文檔對象組成的樹狀結構,對於每一個特定名稱或特定層次的XML 節點而輸出不同的內容,這個過程比較復雜,代碼量大,需用進行很多的狀態判斷。而XSLT 則使用一種簡潔明了的標記語言實現了相同的邏輯。因此XSLT從程序邏輯的角度看類似支持 遞歸的編程語言,而且是專門處理XML文檔的。

XSLT轉換過程會涉及到三個文本文檔 ,一個是要處理的原始XML文檔,第二個就是XSLT樣式表文檔,該文檔包含了XSLT代碼,XSLT 代碼本身就是XML格式,但使用了XML的名稱空間。第三個就是XSLT處理輸出的文本文檔,注 意,此處輸出的是純文本文檔,這個文檔具體是什麼格式完全靠XSLT代碼來決定,可以是另 外一個XML文檔,HTML文檔,SQL語句字符串或者其他任意格式的字符串數據等等,XSLT轉換 只能輸出純文本文檔,此外就沒有限制輸出文檔的具體格式。

XSLT范例

下面使用一個XSLT范例來說明XSLT處理過程。

在這個示意圖中有三個圖片, 第一個是原始的包含數據的XML文檔,第二個是XSLT樣式表文檔的內容,第三個就是轉換結果 。XSLT代碼如下

<xsl:stylesheet version='1.0' xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method='xml' />
  <xsl:template match='/'>
    <html>
      <body>
        <table border='1'>
           <xsl:for-each select="Table/Record">
             <tr>
              <xsl:for-each select="*">
                <td>
                   <xsl:value-of select="." />
                </td>
               </xsl:for-each>
            </tr>
           </xsl:for-each>
        </table>
       </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

數據XML文檔是一個很簡單的XML文檔,此處不加 說明了。重點說說XSLT樣式表文檔,可以看到XSLT樣式表文檔本身一個XML文檔。它采用XML 的樹狀結構來描述遞歸處理過程,也比較好理解。

在樣式表文檔中,根元素為 xsl:stylesheet ,裡面定義了一個名為xsl的名稱空間,這個根節點及其屬性值都是固定的 。

xsl:output 元素是可選的,它的method屬性用於指定輸出文檔的格式,可以設置 為xml,html或text值。此處使用xml輸出樣式,說明輸出的文檔是XML格式的,XSLT轉換會盡 量生成XML文檔,但不作保證,因此仍然有可能生成不合格的XML文檔。

xsl:template 用於定義一個XSLT模板,模板類似編程語言中的函數,可實現XSLT代碼的重用。模板可以使 用name屬性定義名稱,也可以使用match屬性定義匹配的XPath路徑,這個模板使用了match屬 性來匹配XML文檔本身。

然後是 html 元素,由於html元素沒有使用xsl的前綴,因此 不屬於xslt代碼,因此將原樣輸出,跟著後面的body,table元素也是一樣的。

xsl:for-each 元素類似C#中的foreach 語法結果,表示循環遍歷元素,它使用 select屬性指定一個XPath相對路徑,XSLT使用這個相對路徑查詢所有要遍歷的XML節點,此 時當前節點就是XML文檔本身,因此XSLT處理器會調用XmlDocument的SelectNodes 函數來獲 得要遍歷的XML節點,函數的參數就是Table/Record。於是我們開始循環遍歷所有的Record元 素了。

在循環遍歷Record元素時,對每一個Record元素都要輸出xsl:for-each的子節 點,首先是 tr 元素,這不是XSLT元素,因此原樣輸出。這裡還套嵌定義了另外一個for- each元素,於是我們又開始了一個新的循環遍歷了,新的循環指定的相對XPath路徑是一個星 號,表示匹配所有名稱的子元素,這類似DOS命令Dir中使用星號匹配所有文件。此處表示循 環遍歷Record元素下面所有的字段元素。

對每一個字段元素,首先輸出td 元素,然 後處理xsl:value-of 元素,xsl:value-of 表示輸出指定相對路徑的節點的值,這裡指定的 XPath是一個點號,表示當前節點本身,由於當前節點是XML元素,因此也就輸出元素的文本 內容,相當於輸出XmlElement的InnerText 屬性值。

為了讓大家 更清楚的了解XSLT執行過程,我寫了一段C#代碼來模擬實現這個XSLT轉換過程,代碼在演示 程序的 codexslt.aspx 中。代碼如下

// 此處代碼動態構造 xml 文檔對象結 構來輸出XML文檔
System.Xml.XmlDocument XmlDoc = new System.Xml.XmlDocument ();
-------------- 查詢數據庫,填充XmlDoc --------------------------
// 保存輸出結果的緩沖區
System.IO.StringWriter myResult = new System.IO.StringWriter();
myResult.WriteLine("<html>");
myResult.WriteLine("  <body>");
myResult.WriteLine ("    <table border='1'>");
// 模擬 <xsl:for -each select="Table/Record">
foreach( System.Xml.XmlNode node in XmlDoc.SelectNodes("Table/Record"))
{
   myResult.WriteLine("    <tr>");
  // 模擬 <xsl:for -each select="*">
  foreach( System.Xml.XmlNode node2 in node.SelectNodes("*"))
  {
    myResult.Write("       <td>");
    // 模擬 <xsl:value-of select="." />
    myResult.Write( node2.InnerText );
    myResult.WriteLine("</td>");
  }
   myResult.WriteLine("    </tr>");
}
myResult.WriteLine("    </table>");
myResult.WriteLine("  </body>");
myResult.WriteLine ("</html>");
myResult.Close();

代碼很簡單,這裡 我就不詳細說明了。

這裡只是展示了一個非常簡單的XSLT轉換過程,XSLT和XPath語 法不少,但花點時間是可以記下來的,編寫XSLT模板是很有技巧性的。一般的我們要設計 XSLT模板,首先獲得要轉換的XML文檔樣本以及所需轉換結果的樣本,這兩個樣本可能相差非 常大,所有的差別都需要依靠XSLT轉換模板來彌補,此時XSLT模板的編寫不只是XSLT元素和 函數的堆砌,而是需要同時兼顧輸入和輸出,還需要使用面向過程的編程思想。有時還需要 編程對XSLT轉換器進行擴展。

XML/XSLT在WEB開發中的應用

XML/XSLT技術在 WEB開發中可以發揮很大的應用,可以為WEB開發提供一種新的HTML頁面生成方式。

一 般的在WEB開發中使用XML/XSLT技術主要有兩種模式,一個是在服務器端執行XSLT轉換,另一 個是在客戶端執行XSLT轉換。

在服務器端執行XSLT轉換時,應用系統的業務模塊生成 包含要顯示的數據的XML文檔,然後調用事先寫好的XSLT模板文檔,執行XSLT轉換,轉換結果 一般是HTML文檔,當然也可以是其他類型的文本文檔,此時客戶端就可以將生成的HTML文檔 直接作為頁面響發送到客戶端浏覽器中。客戶端浏覽器接受HTML文檔並顯示出來。在這個過 程中,服務器端生成的XML文檔,XSLT轉換生成的HTML文檔都是臨時生成的文檔,都可以存留 在內存中,用完即可清除掉,不需要寫到磁盤文件中。

在客戶端執行XSLT轉換時,應 用系統的業務模塊生成包含要顯示的數據的XML文檔,加上XSLT轉換信息標記,直接發送到客 戶端浏覽器,客戶端浏覽器獲得這個XML文檔,根據其中的XSLT轉換信息標記,從服務器上下 載指定名稱的XSLT文檔。然後調用自己的XSLT轉換器進行轉換,在內存中生成了HTML文檔並 顯示出來。此時顯示的HTML頁面不會出現在浏覽器的緩沖文件夾中,也看不到HTML源代碼, 只能看到XML的源代碼。

由於XSLT轉換是國際標准,在服務器端的轉換結果和在客戶 端的轉換結果是一樣的。因此兩種模式下浏覽器中顯示的頁面內容是一樣的。

在傳統的WEB 開發中,我們都是直接使用業務系統拼湊出HTML字符串來生成要顯示的HTML頁面。雖然在 ASP.NET中大量使用Web控件來簡化開發,但web控件內部還是拼湊HTML字符串的。使用程序代 碼來拼湊HTML字符串會影響程序代碼的可讀性,很容易使得程序代碼雜亂無章,而且生成的 HTML可讀性差。

若使用XML/XSLT技術則可以有效的改善這種情況,由於XML文檔格式 檢查非常嚴格,因此這就使得程序代碼生成XML文檔過程准確,不得出現錯誤,在這個環境下 迫使程序員注意保持程序代碼質量。而且生成的XML文檔不只用於生成HTML頁面,還能方便的 向其他程序模塊提供數據,並可充當WebService。

考察WEB應用中生成的HTML代碼, 可以發現,大量的HTML頁面中用於實現頁面各種動態效果和頁面格式的HTML代碼多於直接顯 示數據的HTML代碼,而且HTML代碼普遍重復。這使得HTML頁面代碼臃腫,文件大,這會使得 客戶端浏覽器下載頁面緩慢。當采用XML/XSLT技術並在客戶端執行XSLT轉換時,由於服務器 端發送的XML文檔非常簡潔,只包含純粹的數據,並沒有其他冗余的代碼,因此文檔小,下載 快。與之配套的XSLT模板也是經過分析處理的,代碼重復少,因此XSLT文件也小,這樣客戶 端浏覽器以前要下載一個很大的HTML文檔,而現在只要下載兩個較小的文檔,這縮短了浏覽 器下載數據的時間。

除了改善數據傳輸過程,浏覽器自己執行XSLT轉換,這樣能將一 部分的工作量從服務器端轉移到客戶端,此時服務器端只要快速生成包含數據的XML文檔即完 成工作。由於XSLT是廣泛采用的國際標准,此時WEB系統能可靠的使用客戶端的運算能力,從 而減少服務器端運算壓力,而利用客戶端長期閒置的運算能力。

雖然XML/XSLT技術具 有很大的優勢,但在實際開發中仍然存在不小的問題,其中最大的問題就是編制XSLT模板文 件成本高。我們在開發WEB系統中使用了很多開發工具,包括VS.NET的WEB窗體設計器,美工 人員使用的FrontPage,Dreamwave等等,都是用於生成HTML文檔的,而HTML文檔要求不嚴格 ,很多內容還不符合XML規范,因此需要使用各種方法將這些HTML文檔轉換為標准的XML文檔 ,然後還需要分析頁面結構,將這些XML文檔加工成XSLT文檔。在目前的技術條件下,這個過 程成本比較大,使得XML/XSLT技術難於推廣和普及。在此建議大家多多思考,如何低成本的 將HTML文檔轉換為XSLT文檔。

而且XML/XSLT技術調試比較困難,對開發者要求很高, 這也加大了這個技術的應用成本。而且目前的web系統中大量使用的WEB控件沒有考慮到 XML/XSLT技術,這也阻礙了這種新技術的應用。

使用C#執行XSLT轉換

在演示 程序中,其中有些代碼就是使用C#來執行XSLT轉換的。

record.aspx

演示程序 中record.aspx演示了在服務器端執行XSLT轉換,打開這個頁面的C#代碼中,在Page_Load函 數中,首先是查詢數據庫並生成一個包含數據的XML文檔。然後我們使用了一個名為xsl的頁 面參數,這個參數就指定了使用XSLT模板文件。若用戶指定了該參數,我們開始執行XSLT轉 換。

首先是創建一個XslTransform對象,調用它的Load函數來加載用戶指定的XSLT模 板文件,然後調用它的Transform函數,這個函數有四個參數,第一個就是包含數據的XML文 檔對象,第二個是XSLT轉換參數的列表,此處未用,第三個就使輸出轉換結果的流對象,我 們就使用頁面輸出流,最後一個是XML文檔解析對象,此處未用。

string strXSLRef = this.Request.QueryString["xsl"] ;
if( strXSLRef != null && strXSLRef.Length > 0 )
{
  // 根據頁面參數指定的 XSLT樣式表名稱執行XSLT轉換
  strXSLRef = this.Server.MapPath( strXSLRef );
  System.Xml.Xsl.XslTransform transform = new System.Xml.Xsl.XslTransform();
  transform.Load( strXSLRef );
   transform.Transform( XmlDoc , null , this.Response.Output , null );
}

可以看到在C#中執行XSLT轉換是非常簡單的,只要創建一個XslTransform對 象,使用Load函數加載XSLT模板,使用Transform函數來執行XSLT轉換即可。

recordxml.aspx

演示程序中的recordxml.aspx演示了在客戶端執行XSLT轉換 ,打開這個頁面的C#代碼,在Page_Load函數中,可以看到是查詢數據庫並使用 XmlTextWriter輸出包含數據的XML文檔。其中有這麼一段代碼,首先判斷一個名為xsl的頁面 參數是否存在,若存在則調用xmlwriter的WriteProcessingInstruction方法輸出一段名為 xml-stylesheet的XML指令,這個指令的 href 屬性值就使頁面參數指定的XSLT模板文件名。

// 輸出XSLT樣式表信息頭
string strXSLRef = this.Request.QueryString["xsl"] ;
if( strXSLRef != null && strXSLRef.Length > 0 )
{
  xmlwriter.WriteProcessingInstruction (
    "xml-stylesheet" ,
     "type='text/xsl' href='" + strXSLRef + "'");
}

客戶端浏覽器解析下載的XML文檔,若遇到這個 這段XML指令根據其中的href屬性下載XSLT模板文件,然後執行XSLT轉換,將生成的轉化結果 再作為HTML文檔顯示出來。

在這個頁面中,服務器端只負責輸出數據XML文檔,並提 供XSLT模板文件下載,而XSLT轉換就給客戶端浏覽器處理,這樣就能減少服務器端的工作量 並利用客戶端的運算能力。

注意這裡的xml-stylesheet指令只對浏覽器有效,一般其 他的程序處理XML文檔時會忽略掉這個XML指令。即使我們在服務器端使用XslTransform對象 執行XSLT轉換,這個XML指令也是毫無作用的,就像不存在一樣。

使用C#執行XPath查 詢

演示程序中的recordxpath.aspx就演示了使用C#執行XPath查詢。打開這個頁面的 界面設計,可以看到其界面是比較簡單地,其中一個單行文本框用於輸入XPath字符串,一個 大的多行文本框用於顯示查詢結果,還有一個按鈕用於點擊執行操作。頁面代碼主要在這個 按鈕的點擊事件處理中。

雙擊這個按鈕,可以看到該按鈕的點擊事件處理代碼。在該 處理中,首先調用CreateRecordXMLDocument函數來獲得包含數據的XML文檔對象,生成XML文 檔的過程可以參考record.aspx的說明。

程序生成包含數據的XML文檔後,在從單行的 文本輸入框獲得用戶輸入的XPath字符串,若用戶輸入的內容,則對XML文檔的根節點調用 SelectNodes方法,執行XPath查詢,SelectNodes函數返回一個XmlNodeList列表,該列表中 的元素類型是XmlNode。我們遍歷這個列表,對其中每一個XML節點對象獲得它的XML字符串, 然後進行輸出。

若用戶沒有輸入XPath字符串,則直接輸出XML文檔根節點的內容。

在這裡我們定義了GetXMLString 函數,這個函數主要是返回指定的XML節點對象的帶 縮進的XML字符串。用於取代Xml節點的OuterXml屬性。

小結

在本課程中,我 們了解了XPath,XML/XSLT的基礎知識。並演示使用C#使用XPath和XML/XSLT技術。

XML及其派生的技術都是很重要的國際標准技術,對現代WEB開發具有很大的影響力, XML技術是一種優質的軟件開發技術,因此大家要花點時間好好學習,熟練掌握XML及其派生 技術將大大提高大家的軟件開發能力。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved