最近在做一些网页信息采集的工作,说通俗点就是爬虫工具,要监控页面中某一部分内容是否发生变化。起初考虑用正则表达式去匹配网页源码,经过咨询有经验人士,推荐使用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的更多相关文章

  1. XStream将java对象转换为xml时,对象字段中的下划线“_”,转换后变成了两个的解决办法

            在前几天的一个项目中,由于数据库字段的命名原因 其中有两项:一项叫做"市场价格"一项叫做"商店价格" 为了便于区分,遂分别将其命名为market ...

  2. .NET Core采用的全新配置系统[9]: 为什么针对XML的支持不够好?如何改进?

    物理文件是我们最常用到的原始配置的载体,最佳的配置文件格式主要由三种,它们分别是JSON.XML和INI,对应的配置源类型分别是JsonConfigurationSource.XmlConfigura ...

  3. WebApi接口 - 响应输出xml和json

    格式化数据这东西,主要看需要的运用场景,今天和大家分享的是webapi格式化数据,这里面的例子主要是输出json和xml的格式数据,测试用例很接近实际常用情况:希望大家喜欢,也希望各位多多扫码支持和点 ...

  4. XML技术之DOM4J解析器

    由于DOM技术的解析,存在很多缺陷,比如内存溢出,解析速度慢等问题,所以就出现了DOM4J解析技术,DOM4J技术的出现大大改进了DOM解析技术的缺陷. 使用DOM4J技术解析XML文件的步骤? pu ...

  5. UWP开发之Mvvmlight实践六:MissingMetadataException解决办法(.Net Native下Default.rd.xml配置问题)

    最近完成一款UWP应用,在手机端测试发布版(Release)的时候应用莫名奇妙的强行关闭,而同样的应用包在PC端一点问题都没有,而且Debug版在两个平台都没有问题,唯独手机的Release版有问题. ...

  6. PHP中遍历XML之SimpleXML

    简单来讲述一些XML吧,XML是可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言.XML是当今用于传输数据的两大工具之一,另外一个是json. 我们在PHP中使用XML也是用来传输数据, ...

  7. Asp.Net 操作XML文件的增删改查 利用GridView

    不废话,直接上如何利用Asp.NET操作XML文件,并对其属性进行修改,刚开始的时候,是打算使用JS来控制生成XML文件的,但是最后却是无法创建文件,读取文件则没有使用了 index.aspx 文件 ...

  8. Mybatis XML配置

    Mybatis常用带有禁用缓存的XML配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  10. C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素”

    Q: 在反序列化 Xml 字符串为 Xml 对象时,抛出如下异常. 即在 XML文档(0, 0)中有一个错误:缺少根元素. A: 首先看下代码: StringBuilder sb = new Stri ...

随机推荐

  1. C#中Socket用法,多个聊天和单一聊天。

    自己琢磨Socket刚刚几天,所以整理出来和大家共享一下.废话少说直接进入正题. 在C#中提供了两种网络服务,一种是Socket类,另一种是TcpListener(服务器),TcpClient(客户端 ...

  2. 使用Node.js作为后台进行爬虫

    看了一遍又一遍Node.js但是没过多久就又忘了,总想找点东西来练练手,就发现B站首页搜索框旁边的GIF图特别有意思,想着是不是可以写一个小Node.js项目把这些图全部扒下来,于是带着复习.预习与探 ...

  3. PHP实战开发教程

    对于PHP初学者来说,一上手就学习庞大的PHP语法无疑很打击自信心.其实即便是很熟练的程序员,也未必对所有的语法非常熟悉.通常熟练的程序员比普通的程序员的优势在于对基本语法的理解非常透彻,而且常用的一 ...

  4. ng-html 报 不安全 警告解决办法

    app.filter('to_trusted',['$sce',function($sce){ return function(text){ return $sce.trustAsHtml(text) ...

  5. linux下删除内核

    一.概述 笔者的Ubuntu系统刚安装成功后,就不知道怎么会有多个内核,但实际上默认运行的只有一个.在grub启动界面多余的启动项和多余内核占用的存储空间迫使我产生了铲除多余内核的冲动. 最近,自己从 ...

  6. 面向对象js瀑布流效果

    index.html <!doctype html><html lang="en"> <head>  <!--网站编码格式,UTF-8 国 ...

  7. golang开发android环境搭建_window

    golang开发android环境搭建介绍 一 安装依赖软件: git:版本管理 go:  go开发环境(版本>=1.5),可直接下载window版的go安装包. android studio: ...

  8. Junit4学习笔记--方法的执行顺序

    package com.lt.Demo.TestDemo; import java.util.Arrays; import java.util.Collection; import org.junit ...

  9. 面试:如何找出字符串的字典序全排列的第N种

    1.题目 如何找出字符串的字典序全排列的第N种?(字符串全排列的变种) 2.思路 主要想通过这题,介绍一下康托展开式.基于康托展开式可以解决这个问题. 一般的解法:①求出所有全排列 ②按照字典序排个序 ...

  10. c++ RAII 资源管理就是初始化

    RAII:(Resource Acquisition Is Initialization),也就是“资源获取就是初始化”,是C++语言的一种管理资源.避免泄漏的惯用法.C++标准保证任何情况下,已构造 ...