模板引擎開發(三)-自訂標籤的處理

來源:互聯網
上載者:User

自訂標籤大致可以理解為一個HTML代碼塊,也可以指向一個HTML檔案。

在模板頁中,很多地方需要相同的內容,例如頁面的頭部、尾部等,這個時候,可以利用自訂標籤來定義HTML代碼,然後在模板頁中引用就可以了。

自訂標籤的格式如下:
{%@ pageTop%} 頁面頂部的頂部的自訂標籤;

自訂標籤中的HTML代碼,我用了XML來記錄,當然也有可視化的編輯介面來操作,在這裡就不再綴述,只是說明一下原理即可,XML如下:

  <Tag Uid="5895643">      <Name>PageTop</Name>      <Type>page</Type>      <Intro><![CDATA[所有頁面的頂部]]></Intro>      <Page>PageTop.html</Page>      <Context><![CDATA[<div id="pagetop">logo 資訊化動力核心 </div><div></div>]]></Context>    </Tag>

上述代碼,標明了自訂標籤的唯一標識、名稱、類型(指定某個頁面)、介紹、html檔案名稱、html代碼塊;

說到這裡就簡單了,我們只需要把自訂標籤從模板頁中檢索出來,替換成HTML代碼就行了。代碼如下:

/// <summary>        /// 將模板內容中的所有自訂標籤,替換為實際的值        /// </summary>        /// <param name="html">要處理的模板對象</param>        /// <returns></returns>        public string Transact(TemplateBuider.PageTransact.Html html)        {            string patt = @"{%@\s*(\S[^\s%]+)\s*%}";            Regex rex = new Regex(patt, RegexOptions.Singleline);            MatchCollection mc = rex.Matches(html.HtmlContext);            for (int i = 0; i < mc.Count; i++)            {                Match ma = mc[i];                string key = ma.Groups[1].Value;                //擷取當前標籤對象                Song.TemplateManager.Tags.CustomTag custom = _tags.Find(delegate(TemplateManager.Tags.CustomTag p) { return p.Name.ToLower() == key.ToLower(); });                if (custom == null) continue;                //轉換自訂標籤中的路徑,使之與當前模板頁為相對路徑                string context =_replacePath(html, custom);                //將自訂標籤合并到的模板                html.HtmlContext = Microsoft.VisualBasic.Strings.Replace(html.HtmlContext, ma.Value, context, 1, -1, Microsoft.VisualBasic.CompareMethod.Text);            }            return html.HtmlContext;        }

上述代碼有一些是我系統中相關方法,大家不必關注,關鍵是Regex。

 

可這個時候,有個問題。各個模板頁並不在一個檔案夾下,路徑各不相同,自訂標籤中的HTML如果有超連結,在模板頁引用後,如果只是簡單的替換,這些超連結就有可能出錯,找不到指定的內容。所以,我們必須將自訂標籤中的連結化物件轉換成當前模板的路徑名。

思路是這樣的,首先找出自訂標籤的路徑,如果自訂標籤是指向HTML檔案的,則按Html路徑;如果是純HTML代碼,則以當前模板庫的路徑為路徑;自訂標籤中的所有連結,包括超連結、CSS引用、Js引用、iframe等,轉換為相對於自訂標籤路徑的路徑;然後找當前模板頁的路徑;將所有的連結轉換為當前模板頁的路徑。

這中間牽涉到一個演算法,從A檔案到B檔案的相對路徑。舉例說:A檔案在/3/4/5/q/w/a.html,B檔案在/3/4/6/s/b.html,如果A檔案中寫一個超連結引用B檔案,這個超連結怎麼寫?
我這裡寫了一個方法。計算兩個檔案的相對路徑,代碼如下:

       /// <summary>        /// 計算兩個檔案的相對路徑        /// </summary>        /// <param name="baseFile">用於參照的檔案,就從當前檔案開始尋找另一個檔案</param>        /// <param name="targetFile">目標檔案,就是求它的相對路徑</param>        /// <returns>返回targetFile相對於baseFile的相對路徑</returns>        private string _getRelativePath(string baseFile, string targetFile)        {            baseFile = baseFile.Replace("\\", "/");            baseFile = baseFile.ToLower();            targetFile = targetFile.ToLower();            //            while (baseFile.IndexOf("/") > -1 && targetFile.IndexOf("/") > -1)            {                string b = baseFile.Substring(0, baseFile.IndexOf("/"));                string t = targetFile.Substring(0, targetFile.IndexOf("/"));                if (b != t) break;                                baseFile = baseFile.Substring(baseFile.IndexOf("/") + 1);                targetFile = targetFile.Substring(targetFile.IndexOf("/") + 1);                           }            string path = "";            while (baseFile.IndexOf("/") > -1)            {                baseFile = baseFile.Substring(baseFile.IndexOf("/") + 1);                path += "../";            }            return path + targetFile;        }

有了上面的方法,就好處理了,真正的超連結轉換,就是正則匹配處理了。方法如下:

        /// <summary>        /// 將模板頁中的路徑處理成相對於當前模板頁的路徑        /// </summary>        /// <param name="html"></param>        /// <param name="tag"></param>        /// <returns></returns>        private string _replacePath(TemplateBuider.PageTransact.Html html, TemplateManager.Tags.CustomTag tag)        {            string context = tag.Context;            //處理自訂標籤中的超連結,使其相對於當前檔案路徑                        string cutomPath = _cutomPath(tag);            //將超連結處理為相對於模板頁的路徑            string linkExpr = @"(?<=\s+)(?<key>href|src|action|background[^=""']*)=([""'])?(?<value>[^'"">]*)\1?";            Regex regex = new Regex(linkExpr, RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);            MatchCollection mc = regex.Matches(tag.Context);            foreach (Match m in mc)            {                string link = m.Groups["value"].Value.Trim();                if (link == "") continue;                //外網連結不處理,如Http://開頭的超連結                if (new Regex(@"[a-zA-z]+://[^\s]*", RegexOptions.Singleline).IsMatch(link))                    continue;                //根路徑不處理,如/manage/index.aspx,第一個字元是/                if (new Regex(@"^\/\w+.").IsMatch(link))                    continue;                //如果是參數標籤,則不處理                if (new Regex(@"^{.+").IsMatch(link))                    continue;                //將超連結轉換為相對於靜態化目錄的路徑                link = _getCutomLinkPath(cutomPath, link);                //將超連結轉換為基於當前模板頁的相對路徑                link = _getRelativePath(html.TagetFile, link);                link = m.Groups[2].Value + "=\"" + link + "\"";                context = context.Replace(m.Value, link);            }            return context;        }        

在上述代碼中,根路徑不處理、站外連結不處理、以{開頭的連結不處理。

總結

我的這個自訂標籤功能並不強,雖然自訂標籤中也可以有其它組件,但其本質未變,只是HTML代碼塊的替換。本來想寫帶參數的自訂標籤呢,這樣就更類似於asp.net的使用者控制項,精力有限,暫時先這樣吧。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.