实现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
    }

你可能感兴趣的:(实现html转Xml)