[OpenAPI] html標籤分析

來源:互聯網
上載者:User

     個人空間的OpenAPI與facebook非常接近(從需要求上就要做成一樣),所以我們在hi中也將會使用類擬於fbml這樣的自訂標籤(himl)。在對notifications.send介面的開發中需要傳入notification參數,這個參數是通知的內容,其實就是一些html和himl標籤混合在一起的字串,其中有一個需求:使用者傳進一個UserName參數要求我們把它變成這個使用者的真實姓名,例如:<hi:name id="billok" />。這裡就是一個himl自訂標籤了。我們要做的工作就是要解析類擬的自定標籤把它轉換成真實姓名。

     架構還是有點複雜,為了表達清楚點,這裡不談很多細節,只列一下這個subject相關的內容。

     首先,應用程式把notification參數傳入notifications.send介面後,會經過一點的流程把參數html傳進如下一個處理請求的基類的方法:

string ParseContent(string html){}  這個方法是使用者分析html參數把其中的himl標籤進行特殊處理。

        protected virtual string ParseContent(string html)
        {
            //載入html到HtmlDocument
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(HttpUtility.HtmlDecode(html));

            //遍曆第一層節點
            foreach (HtmlNode node in doc.DocumentNode.ChildNodes)
            {
                HtmlUtil.ForEach(node);
            }

            return doc.DocumentNode.OuterHtml;
        }

這裡我們使用了HtmlAgilityPack對html分析組件,首先把html字串加裁成HtmlDocument對象,這樣就會自動分析出文檔的dom樹結構,然後把我們通過遍曆第一層節點,使用HtmlUtil.ForEach處理第一層根節點,處理完後就把所有的html進行輸出。使用HtmlAgilityPack的好處是可以方便的對dom進行操作,可以刪除節點和替換節點,不過相信還有更好的類庫可以使用或者以後改為LINQ to xml進行處理。

     我們還是詳細看一下ForEach方法的實現吧。

        public static void ForEach(HtmlNode node)
        {
            if (node.NodeType != HtmlNodeType.Element)
            {
                return;
            }
            else
            {
                if (!node.HasChildNodes)
                {
                    //分葉節點
                    HandleNode(node);
                }
                else
                {
                    foreach (HtmlNode childNode in node.ChildNodes)
                    {
                        ForEach(childNode);
                    }
                    //子節點:有子與有父節點
                    HandleNode(node);
                }
            }
        }

這裡實際上是一個遞迴操作,如果傳進的節點不是一個Element元素(例如:不帶標籤的純檔案,註解等),這樣的node我們是不需要處理的,所以就直接return終結迴圈就好了。對於Element節點的處理,就只分為有子節點和沒有子節點的情況就行,如果有子節點的話就再遍曆子節點並遞迴調用ForEach方法,目的就是把有Element處理一遍。你也發現了我們對節點的處理又被封裝到另一個方法中了HandleNode:

        private static void HandleNode(HtmlNode node)
        {
            //分析節點
            IHtmlTag iHtmlTag = ObjectFactory.CreateIHtmlTag(node.Name);
            Dictionary<string, string> dict = new Dictionary<string, string>();
            //dict.Add("HtmlNode_OuterHtml", node.OuterHtml);//可以傳入節點的全部html,以作進一步處理
            foreach (HtmlAttribute attr in node.Attributes)
            {
                if (!dict.ContainsKey(attr.Name))
                {
                    dict.Add(attr.Name, attr.Value);
                }
            }
            HtmlTag htmlTag = iHtmlTag.Handle(dict);

            //處理節點
            switch (htmlTag.HandleType)
            {
                case HtmlTagHandleType.Remove:
                    if (node.ParentNode != null)
                        node.ParentNode.RemoveChild(node);
                    break;
                case HtmlTagHandleType.Replace:
                    if (node.ParentNode != null)
                    {
                        HtmlNode newNode = HtmlNode.CreateNode(htmlTag.Html);
                        node.ParentNode.ReplaceChild(newNode, node);
                    }
                    break;
                case HtmlTagHandleType.Unknown:
                default:
                    //不做任務處理
                    break;

            }
        }

這個方法分為兩個步聚:分析節點和處理節點,並且利用了IOC模式。

IOC模式是系統架構的一部分,這裡就不詳細談了,你只要知道從ObjectFactory.CreateIHtmlTag方法可以得到標籤名(如:hi:name)所以指定的關於IHtmlTag介面的一個實現,如果沒有合符處理的實現就會使用一個預設實現(就是告訴"處理節點"步聚什麼都不用做)。對於IHtmlTag介面我們看一下定義:

    public enum HtmlTagHandleType
    {
        Unknown,
        Remove,
        Replace,
    }

    public class HtmlTag
    {
        public HtmlTagHandleType HandleType { get; set; }
        public string Html { get; set; }

        public HtmlTag()
        {
            HandleType = HtmlTagHandleType.Unknown;
            Html = string.Empty;
        }
    }

    public interface IHtmlTag
    {
        HtmlTag Handle(IDictionary<string, string> attributes);
    }

IHtmlTag介面只有一個方法

HtmlTag Handle(IDictionary<string, string> attributes); 接受一個節點屬性的索引值對字典,返回對這些索引值對進行處理的結果。

返回的HtmlTag可以指示出需要後續進行怎麼樣的操作(HtmlTagHandleType),以及處理完後的html

Okay! 對節點進行分析後得到HtmlTag,現在就可以進行節點處理的工作了。節點的處理方式以HtmlTagHandleType的返回為準,分別是Remove刪除節點,Replace替換節點,不作處理。

經過這些處理後,返加doc.DocumentNode.OuterHtml就可以得到處理後的html內容了。通過實現IHtmlTag介面,可以很方便的添加新的himl標籤對內容時行特殊處理了。並用標籤還可以任竟擴充屬性,例如:<hi:name id="billok,junbiaochen" target="abc" /> 等等。

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.