實現html轉Xml


最近在做一些網頁信息采集的工作,說通俗點就是爬蟲工具,要監控頁面中某一部分內容是否發生變化。起初考慮用正則表達式去匹配網頁源碼,經過咨詢有經驗人士,推薦使用xpath去獲取頁面內容能獲得更好的效率。但是對於html這種寬松語法要求的語言來說,不可能100%地完全符合xml標准,那么就沒法使用xpath,說得更直接點就是:不能把html源碼直接加載到xmldocument中。為了使用xpath,只能對html內容進行轉換或者規范,於是就寫了這么一個方法。

該方法比較地偷懶,借助了開源工具htmlparser獲取html源碼中的所有節點,然后遍歷各個節點,轉換為對應的xmlnode。對於html中有未閉合的節點,在轉換后實際代碼會有一些差別,但是不影響xpath的使用(這也跟如何寫xpath的內容有關)。

實現方式如下,需引用htmlparser的dll

 


    /// <summary>
    /// 解析Xml文件的幫助類
    /// </summary>
    public class XMLHelper
    {
        /// <summary>
        /// 有效名稱的正則表達式
        /// </summary>
        static string validName = @"^[^\$\/;""\!#\)\.]+$";

        #region CovertHtmlToXml
        /// <summary>
        /// 轉換html源碼為xml格式
        /// </summary>
        /// <param name="html">html源碼</param>
        /// <returns>xml字符串</returns>
        /// <param name="TargetTag">需轉換的標記名</param>
        public static string CovertHtmlToXml(string html, string targetTag)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                XmlNode xmlDeclaration = doc.CreateXmlDeclaration("1.0", "utf-8", null);
                doc.AppendChild(xmlDeclaration);

                // 借助htmlparser解析html內容
                Parser parser = Parser.CreateParser(html, "GBK");
                // 篩選出指定的節點
                TagNameFilter tnf = new TagNameFilter(targetTag);
                NodeList nodes = parser.Parse(tnf);

                // 創建根節點
                XmlElement root = doc.CreateElement("Tags");

                TagNode tagNode = null;
                Hashtable ht = null;
                XmlAttribute attr = null;
                XmlElement parent = null;
                for (int i = 0; i < nodes.Size(); i++)
                {
                    tagNode = nodes[i] as TagNode;
                    parent = doc.CreateElement(tagNode.TagName);
                    
                    // 添加屬性
                    ht = tagNode.Attributes;
                    foreach (DictionaryEntry ent in ht)
                    {
                        // 查看屬性名是否合法
                        if (Regex.IsMatch(ent.Key.ToString(), validName))
                        {
                            attr = doc.CreateAttribute(ent.Key.ToString());
                            attr.Value = ent.Value.ToString();
                            parent.Attributes.Append(attr);
                        }
                    }// end foreach (DictionaryEntry ent in ht)

                    AppendChild(tagNode, parent, doc);

                    root.AppendChild(parent);
                }
                doc.AppendChild(root);

                return doc.OuterXml;

                //throw new Exception("給定的html文本必須至少包含一個" + targetTag + "節點");
            }
            catch (Exception ex)
            {
                throw new Exception("轉換html內容出錯:" + ex.Message);
            }
        }

        /// <summary>
        /// 添加子節點
        /// </summary>
        /// <param name="tagNode">Html的父節點</param>
        /// <param name="parent">Xml的父節點</param>
        /// <param name="doc">Xml文檔對象</param>
        private static void AppendChild(INode tagNode, XmlNode parent, XmlDocument doc)
        {
            INode node = null;
            XmlNode xmlNode = null;
            XmlAttribute attr = null;
            Hashtable ht = null;

            // 判斷是否包含子節點
            if (tagNode.Children != null && tagNode.Children.Size() > 0)
            {
                for (int i = 0; i < tagNode.Children.Size(); i++)
                {
                    node = tagNode.Children[i];
                    xmlNode = null;
                    attr = null;
                    ht = null;

                    // 如果是html標記節點
                    if (node is TagNode)
                    {
                        TagNode tn = node as TagNode;
                        if (Regex.IsMatch(tn.TagName, validName))
                        {
                            xmlNode = doc.CreateElement(tn.TagName);

                            // 添加屬性
                            ht = tn.Attributes;
                            foreach (DictionaryEntry ent in ht)
                            {
                                // 查看屬性名是否合法
                                if (Regex.IsMatch(ent.Key.ToString(), validName))
                                {
                                    attr = doc.CreateAttribute(ent.Key.ToString());
                                    attr.Value = ent.Value.ToString();
                                    xmlNode.Attributes.Append(attr);
                                }
                            }
                        }
                    }

                    // 如果是文本節點
                    if (node is TextNode)
                    {
                        xmlNode = doc.CreateTextNode((node as TextNode).ToPlainTextString());
                    }

                    if (xmlNode != null)
                    {
                        parent.AppendChild(xmlNode);
                        AppendChild(node, xmlNode, doc);
                    }
                }
            }
        }
        #endregion
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM