1. 程式人生 > >基於xslt的簡單應用開發

基於xslt的簡單應用開發

一.本文所涉及的內容

  1. 本文所涉及的內容
  2. xslt及其應用場景
  3. 簡單應用示例
    1. 轉換示例:通過xslt將xml轉換成html
    2. 基本語法應用示例:變數,迴圈,條件,模板(方法),引數等
    3. 伺服器端轉換方式-結合c#進行方法擴充套件
    4. 繼承(匯入)和過載(重定義)的應用

二.xslt及其應用場景

XSLT可擴充套件樣式錶轉換語言(Extensible Stylesheet Language Transformations)是一種對XML文件進行轉化的語言,它的作用相當於就是樣式表(css)之於HTML檔案,XSLT中的T代表英語中的“轉換”(transformation)。它是XSL(Extensible stylesheet language)規範的一部分。

XSLT一個比較顯著的特點是資料與顯示分離,資料可以根據需要的樣式或者形式進行展示,轉換的方式可以為分為客戶端轉換(需要瀏覽器支援xslt)和伺服器端轉換。  

常用應用場景如下:

第一,將源xml轉換成符合要求的xml、HTML。例如某企業應用介面提供的資料為較為冗餘的xml,可以按需使用xslt將源xml進行精簡轉換成xml或者HTML,同時如果資料來源變化的話,只需要對應的調整xstl轉換檔案即可。
第二,搜尋引擎抓取的HTML解析。此類特點是該抓取的html的格式多樣而且非固定,可使用xslt進行解析成標準格式再進行入庫索引,如果html格式有變化,對應修改xslt模板即可。

XSLT 是如何工作的:


 a)首先XML文件被讀入記憶體當中並存儲為棵結點樹
 b)<xsl:template match=“/”> 模板用來選擇整個樹的根結點
 c)模板中的規則被用來進行結點的匹配從而改變XML 樹的結構
 d)如果還有其它模板,那麼它們必須顯示地從主模板中呼叫 如果還有其它模板,那麼它們必須顯示地從主模板中呼叫
 e)XML 樹中沒有匹配的部分保持原來的狀態不變
 f)模板應用完成後,樹被作為一個新的文字文件輸出出來

(更多請Google XSLT) 

三.簡單應用示例

轉換示例

1.通過xslt將xml轉換成html,通過瀏覽器轉換的方式

xml資料來源檔案:
<?xml version="1.0" encoding="UTF-8"?>
<!--客戶端轉換的xslt-->
<?xml-stylesheet type="text/xsl" href="XSLT_Client.xslt"?>
 <books>
  <book>
    <title>HTML5+CSS3從入門到精通(附1DVD)</title>
    <author>李東博</author> 
    <publisher>清華大學出出版社</publisher>
    <price>42.90</price>
    <year>2015</year>
  </book>
  <book>
    <title>安全之路——Web滲透技術及實戰案例解析(第2版)</title>
    <author>陳小兵</author> 
    <publisher>電子工業出版社</publisher>
    <price>84.90</price>
    <year>2015-09-1</year>
  </book>
</books>

客戶端轉換使用的xlst檔案:
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  
  <xsl:template match="/">
    <xsl:variable name="paraPath" select="/books/book" ></xsl:variable> 
    <html>
      <body>
        <h2>Books List</h2>
        <table border="1">
          <tr bgcolor="#87CEFA">
            <th align="left">Title</th>
            <th align="left">author</th>
            <th align="left">publisher</th>
            <th align="left">price</th>
            <th align="left">year</th>
          </tr>
          <xsl:for-each select="$paraPath">
            <tr>
              <td>
                <xsl:value-of select="title"/>
              </td>
              <td>
                <xsl:value-of select="author"/>
              </td>
              <td>
                <xsl:value-of select="publisher"/>
              </td>
              <td>
                <xsl:value-of disable-output-escaping="yes" select="price"/>
              </td>
              <td>
                <xsl:value-of select="year"/>
              </td>
            </tr>
          </xsl:for-each>
       
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

轉換的結果如下: Books List
Title author publisher price year
HTML5+CSS3從入門到精通(附1DVD) 李東博 清華大學出出版社 42.90 2015
安全之路——Web滲透技術及實戰案例解析(第2版) 陳小兵 電子工業出版社 84.90 2015-09-1

2.通過xslt將xml轉化成html,通過伺服器端轉換的方式

xml資料來源檔案(不需要把xslt檔案連結到xml當中):
<?xml version="1.0" encoding="UTF-8"?> 
<books>
  <book id="1">
    <title>HTML5+CSS3從入門到精通(附1DVD)</title>
    <author>李東博</author> 
    <publisher>清華大學出出版社</publisher>
    <price>42.90</price>
    <year>2015</year>
  </book>
  <book id="2">
    <title>安全之路——Web滲透技術及實戰案例解析(第2版)</title>
    <author>陳小兵</author> 
    <publisher>電子工業出版社</publisher>
    <price>84.90</price>
    <year>2015-09-1</year>
  </book>
</books>
xslt檔案和客戶端轉換對應的xslt檔案是一樣的,轉換的結果也是一樣的。 基本語法應用示例:變數,迴圈,條件,模板(方法),引數等   先看對應的轉換的xslt檔案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fun_c="urn:format" exclude-result-prefixes="fun_c">

  <xsl:template match="/">
    <!--變數-->
    <xsl:variable name="paraPath" select="/books/book" ></xsl:variable>
    <html>
      <head>
      <script type="text/javascript"  language="javascript" >
        var firstName = "<xsl:value-of select="$paraPath[@id='1']/title"/>";
        alert(firstName);
      </script> 
      </head>
      
      <body>
        <h2>Books List</h2>
        <table border="1">
          <tr bgcolor="#87CEFA">
            <th align="left">Title</th>
            <th align="left">author</th>
            <th align="left">publisher</th>
            <th align="left">price</th>
            <th align="left">year</th>
          </tr>
          <!--模板(方法呼叫)-->
          <xsl:call-template name="Each.Output">
            <!--傳參-->
            <xsl:with-param name="paraPath" select="$paraPath"/>
          </xsl:call-template>
        </table>
      </body>
    </html>
  </xsl:template>

  <!--模板(方法定義)-->
  <xsl:template  name="Each.Output">
    <xsl:param name="paraPath"></xsl:param>
    <!--迴圈-->
    <xsl:for-each select="$paraPath">
      <!--根據屬性id進行排序-->
      <xsl:sort select="@id" data-type="number"/>
      <tr>
        <td>
          <xsl:value-of select="title"/>
        </td>
        <td>
          <xsl:value-of select="author"/>
        </td>
        <td>
          <!--c#擴充套件方法SetRed(string value)呼叫-->
          <xsl:value-of disable-output-escaping="yes" select="fun_c:SetRed(publisher)"/>
        </td>
        <td>
          <!--內建方法,字串合併-->
          <xsl:value-of select="concat(price,'元')"/>
        </td>
        <td> 
          <xsl:value-of select="year"/>
          <!--條件判斷,如果值不為空為並且2015-->
          <xsl:if test="year!=''and year ='2015'  ">
            <xsl:value-of select="'年'"/>
          </xsl:if>
        </td>
      </tr>
    </xsl:for-each>

  </xsl:template>

</xsl:stylesheet>

 其中,<xsl:value-of disable-output-escaping="yes" select="fun_c:SetRed(publisher)"/>這個擴充套件方法需要搭配後臺語言定義,如果使用客戶端瀏覽器轉換,需要註釋掉。

XSLT 含有超過 100 個內建的函式,XQuery 1.0、XPath 2.0 以及 XSLT 2.0 共享相同的函式庫。
這些函式用於字串值、數值、日期和時間比較、節點和 QName 操作、序列操作、邏輯值,等等。關於 XSLT 的內建函式請引數:XSLT 函式參考手冊 和 XPath、XQuery 以及 XSLT 函式

伺服器端轉換方式-結合c#進行方法擴充套件  
有時候內建的方法無法滿足要求,那麼就需要擴充套件方法了,例如上述的fun_c:SetRed(string value)方法。

首先xslt檔案的頭部xmlns:fun_c="urn:format" 定義了一個字首 fun_c而已,也就是名稱空間,沒有什麼特別的意義,但必須與其他用到這個字首的地方保持一致。如果不定義這麼一個名稱空間的話,直接不帶字首的呼叫 SetRed() 函式時,預設為的名稱空間是 fn,而 fn 中是不存這個函式的。

擴充套件函式必須為 public 的:

 /// <summary>
    ///xslt的擴充套件
    /// </summary>
    public class XsltExt
    {
        /// <summary>
        /// 擴充套件方法
        /// 宣告必須為public
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public string SetRed(string str)
        {
            return string.Format("<span style='color:red'>{0}</span>", str);
        }
    }

直接上轉換相關程式碼:
 
        /// <summary>
        /// 載入xslt檔案
        /// </summary>
        private void LoadView(string xsltPath)
        {
            strXsltPath = xsltPath;
            if (Cache && views.Keys.Contains(strXsltPath))
            {
                xct = views[strXsltPath];
            }
            else
            {
                xct = new XslCompiledTransform(Debug);
                var xs = new XsltSettings { EnableScript = true, EnableDocumentFunction = true };
                var settings = new XmlReaderSettings { ProhibitDtd = false };
                // Create the reader.
                var reader = XmlReader.Create(strXsltPath, settings);
                try
                {
                    xct.Load(reader, xs, new XmlUrlResolver());
                    if (Cache)  views.Add(strXsltPath, xct);
                }
                finally
                {
                    reader.Close();
                }
            }
        }

        /// <summary>
        /// 通過xslt檔案轉換XML 
        /// </summary>
        /// <param name="strXmlPath">XML檔案路徑</param>
        /// <returns></returns>
        public string TransferXmlByXslt(string xsltPath, string strXmlPath)
        {
            LoadView(xsltPath);
            string pName = "urn:format";
            string className = "WebApplicationXsltDemo.XsltExt,WebApplicationDemo";

            Type t = Type.GetType(className);
            if (className.Contains(','))
            {
                className = className.Split(',')[0];
            }
            object objEx = t.Assembly.CreateInstance(className);
            XsltArgumentList xal = new XsltArgumentList();
            xal.AddExtensionObject(pName, objEx);
            var fs = new MemoryStream();
            var outputstring = string.Empty;
            try
            {
                ////判斷檔案是否存在
                if (File.Exists(strXmlPath) && File.Exists(strXsltPath))
                {
                    ////載入xml檔案
                    var doc = new XPathDocument(strXmlPath);
                    XPathNavigator nav = doc.CreateNavigator();
                    ////轉換xml
                    xct.Transform(nav, xal, fs);
                    fs.Seek(0, SeekOrigin.Begin);
                    var stream = new StreamReader(fs);
                    outputstring = stream.ReadToEnd();
                    xct.TemporaryFiles.Delete();
                }
                else
                {
                    return string.Empty;
                }
            }
            catch (Exception ex)
            {

            }
            finally
            {
                fs.Close();
                fs.Dispose();
            }
            return outputstring;
        } }

呼叫方法:
   private ActionResult XsltTranslate()
        { 
            string xslt = "XSLT_server.xslt";
            string xml = "XMLFile.xml";
            string serverpath = Server.MapPath("~");   
            XsltTransfer objXsltTransfer = new XsltTransfer();
            <span style="font-family: Arial, Helvetica, sans-serif;">string result </span><span style="font-family: Arial, Helvetica, sans-serif;">= objXsltTransfer.TransferXmlByXslt(serverpath + xslt, serverpath + xml);</span>
            Response.Write(result);
            Response.End(); 
            return new EmptyResult();
        }

繼承(匯入)和過載(重定義)的應用   如果xslt檔案較多,而且可以複用,那麼,模板的匯入和重定義將派上用場。 例如,可以建立一個全域性的global.xslt檔案和通用方法comm.xslt檔案,裡面可以儲存各種全域性的變數和通用方法,再建立一個master.xslt檔案(匯入global.xslt和comm.xslt)做為基礎模板,其他的頁面只需要匯入master.xslt模板頁即可。 XSLT_Comm.xslt
<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <!--定義方法,匯入後可以重寫該方法-->
  <xsl:template  name="Each.Output">
    <xsl:param name="paraPath"></xsl:param>
  </xsl:template>
</xsl:stylesheet>

XSLT_Global.xslt
<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!--  全域性變數定義,也可以重寫此變數 --> 
  <xsl:variable name="paraPath" select="/books/book" ></xsl:variable>
</xsl:stylesheet>

在master.xslt中匯入前面兩個檔案: 

 <xsl:import href="XSLT_Global.xslt"/>
 <xsl:import href="XSLT_Comm.xslt"/>

 xslt+xml+asp.net mvc簡單的應用示例,如上有什麼更好建議或想法,也請大家多多指點。