Asp.Net检查HTML是否闭合以及自动修复

1、htmlCheck类

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Diagnostics;
namespace htmlCheck
{
    /// <summary>
    /// Asp.Net检查HTML是否闭合以及自动修复 http://webapi.cnblogs.com/
    /// </summary>
    class TagsList
    {
        private ArrayList data;

        public int Size
        {
            get
            {
                return data.Count;
            }
        }

        public TagsList()
        {
            data = new ArrayList();
        }

        public void add(String str)
        {
            data.Add(str);
        }

        public string get(int index)
        {
            if (index < data.Count)
                return (string)data[index];
            else
                return null;
        }

        public bool remove(string str)
        {
            if (data.IndexOf(str) == -1) return false;
            data.Remove(str);
            return true;
        }

        public void remove(int index)
        {
            data.RemoveAt(index);
        }
    }

    public class TagsChecker
    {
        /// <summary>
        /// 检查html标签是闭合
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool check(string str)
        {
            TagsList[] unclosedTags = getUnclosedTags(str);

            if (unclosedTags[0].Size != 0)
            {
                return false;
            }
            for (int i = 0; i < unclosedTags[1].Size; i++)
            {
                if (unclosedTags[1].get(i) != null)
                    return false;
            }

            return true;
        }
        /// <summary>
        /// 处理未闭合的html代码
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string fix(String str)
        {
            StringBuilder fixeds = new StringBuilder(); // 存放修复后的字符串
            TagsList[] unclosedTags = getUnclosedTags(str);

            // 生成新字符串
            for (int i = unclosedTags[0].Size - 1; i > -1; i--)
            {
                fixeds.Append("<" + unclosedTags[0].get(i) + ">");
            }

            fixeds.Append(str);

            for (int i = unclosedTags[1].Size - 1; i > -1; i--)
            {
                String s = null;
                if ((s = unclosedTags[1].get(i)) != null)
                {
                    fixeds.Append("</" + s + ">");
                }
            }

            return fixeds.ToString();
        }

        private static TagsList[] getUnclosedTags(String str)
        {
            StringBuilder temp = new StringBuilder(); // 存放标签
            TagsList[] unclosedTags = new TagsList[2];
            unclosedTags[0] = new TagsList(); // 前不闭合,如有</div>而前面没有<div>
            unclosedTags[1] = new TagsList(); // 后不闭合,如有<div>而后面没有</div>
            bool flag = false; // 记录双引号"或单引号‘
            char currentJump = ‘ ‘; // 记录需要跳过‘‘还是""

            char current = ‘ ‘, last = ‘ ‘; // 当前 & 上一个

            // 开始判断
            for (int i = 0; i < str.Length; )
            {
                current = str[i++]; // 读取一个字符
                if (current == ‘"‘ || current == ‘\‘‘)
                {
                    flag = flag ? false : true; // 若为引号,flag翻转
                    currentJump = current;
                    if (flag)
                    {
                        while (i < str.Length && str[i++] != currentJump)
                            ; // 跳过引号之间的部分
                        flag = false;
                    }
                }
                else if (current == ‘<‘)
                { // 开始提取标签
                    current = str[i++];
                    if (current == ‘/‘)
                    { // 标签的闭合部分,如</div>
                        current = str[i++];

                        // 读取标签
                        while (i < str.Length && current != ‘>‘)
                        {
                            temp.Append(current);
                            current = str[i++];
                        }

                        // 从tags_bottom移除一个闭合的标签
                        if (!unclosedTags[1].remove(temp.ToString()))
                        { // 若移除失败,说明前面没有需要闭合的标签
                            unclosedTags[0].add(temp.ToString()); // 此标签需要前闭合
                        }
                        temp.Remove(0, temp.Length); // 清空temp
                    }
                    else
                    { // 标签的前部分,如<div>
                        last = current;
                        while (i < str.Length && current != ‘ ‘
                                && current != ‘ ‘ && current != ‘>‘)
                        {
                            temp.Append(current);
                            last = current;
                            current = str[i++];
                        }

                        // 已经读取到标签,跳过其他内容,如<div id=test>跳过id=test
                        while (i < str.Length && current != ‘>‘)
                        {
                            last = current;
                            current = str[i++];
                            if (current == ‘"‘ || current == ‘\‘‘)
                            { // 判断双引号
                                flag = flag ? false : true;
                                currentJump = current;
                                if (flag)
                                { // 若引号不闭合,跳过到下一个引号之间的内容
                                    while (i < str.Length && str[i++] != currentJump)
                                        ;
                                    current = str[i++];
                                    flag = false;
                                }
                            }
                        }
                        if (last != ‘/‘ && current == ‘>‘) // 判断这种类型:<TagName />
                            unclosedTags[1].add(temp.ToString());
                        temp.Remove(0, temp.Length);
                    }
                }
            }
            return unclosedTags;
        }
    }
}

2、使用方法

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using htmlCheck;//注意,添加这个引用
using System.Text.RegularExpressions;

public partial class ceshi : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string str1 = "<p>tt<table><tr><td>webapi</td></tr><tr><td>323</td></p>";
        string str2 = "tt<u>ss</u><div id=test name=\"<test>\"><a>fds</a></div>";
        Response.Write("\r\n检查文本 " + str1);
        Response.Write("\r\n结果:" + TagsChecker.check(str1));
        Response.Write("\r\n检查文本 " + str2);
        Response.Write("\r\n结果:" + TagsChecker.check(str2));
        Response.Write("\r\n修复文本 " + str1);
        Response.Write("\r\n结果:" + TagsChecker.fix(str1));

    }
}

说明:转载的,已测试,确实闭合修复了,但是闭合的位置不正确

时间: 2024-10-14 00:51:17

Asp.Net检查HTML是否闭合以及自动修复的相关文章

(1)微软.NET战略和ASP.NET简介

摘要:ASP.NET又叫ASP+,但并不仅仅是ASP的简单升级,而是MicroSoft推出的新一代Active Server Pages脚本语言.ASP.NET是微软发展的新型体系结构.NET的一部分,它的全新技术架构会让每一个人的网络生活都变得更简单. 从今天开始,我为大家讲解ASP.NET编程,一开始主要以理论为主,在后面的课程中会加入实操.欢迎你阅读<ASP.NET编程入门>,通过对本书的阅读,我们相信你能够对ASP.NET会有更深入的了解. 首先需要特别指出的是,ASP.NET不仅仅只

ASP.NET --Form身份验证

本文收集自----MSDN 一:Forms 身份验证流程 在 Forms 身份验证方案中,应用程序直接从用户那里收集名字和密码等凭据,并自己判断这些信息的真实性.应用程序不使用 IIS 身份验证,但 IIS 身份验证设置可以影响 Forms 身份验证.作为一项原则,当您使用 Forms 身份验证时,请在 IIS 中启用匿名访问.否则,如果用户未通过 IIS 身份验证,他们甚至无法访问应用程序以便向 Forms 身份验证提供用户名和密码. 此方案中的数据流如下图所示. Forms 身份验证 此图说

IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期概述

本主题概述 ASP.NET 应用程序的生命周期,列出了重要的生命周期事件,并描述了您编写的代码将如何适应于应用程序生命周期.本主题中的信息适用于 IIS 5.0 和 IIS 6.0.有关 IIS 7.0 中的 ASP.NET 应用程序生命周期的信息,请参见 IIS 7.0 的 ASP.NET 应用程序生命周期概述. 在 ASP.NET 中,若要对 ASP.NET 应用程序进行初始化并使它处理请求,必须执行一些处理步骤. 此外,ASP.NET 只是对浏览器发出的请求进行处理的 Web 服务器结构的

ASP.NET 应用程序(Application)生命周期概述

原文:ASP.NET 应用程序(Application)生命周期概述 引用MSDN:ASP.NET 应用程序生命周期概述 本 主题概述应用程序生命周期,列出重要的生命周期事件,并描述如何编写适合应用程序生命周期的代码.在 ASP.NET 中,若要对 ASP.NET 应用程序进行初始化并使它处理请求,必须执行一些处理步骤.此外,ASP.NET 只是对浏览器发出的请求进行处理的 Web 服务器结构的一部分.了解应用程序生命周期非常重要,这样才能在适当的生命周期阶段编写代码,达到预期的效果. 应用程序

ASP.NET(转自wiki)

ASP.NET是由微软在.NET Framework框架中所提供,开发Web应用程序的类库,封装在System.Web.dll文件中,显露出System.Web名字空间,并提供ASP.NET网页处理.扩充以及HTTP通道的应用程序与通信处理等工作,以及Web Service的基础架构.ASP.NET是ASP技术的后继者,但它的发展性要比ASP技术要强大许多. ASP.NET可以运行在安装了.NET Framework的IIS服务器上,若要在非微软的平台上运行,则需要使用Mono平台[2],ASP

ASP基础教程:ASP内建对象Application和Session

在上一篇中作者给大家详细介绍了 ASP 内建对象 Response 的使用方法,在这一篇中作者将继续给大家介绍另两个非常实用且重要的 ASP 的内建对象 Application 和 Session. 在 ASP 的内建对象中除了用于发送.接收和处理数据的对象外,还有一些非常实用的代表 Active Server 应用程序和单个用户信息的对象. 让我们先来看看 Application 对象.在同一虚拟目录及其子目录下的所有 .asp 文件构成了 ASP 应用程序.我们非但可以使用 Applicat

Asp.Net高级知识回顾_HttpModule及应用程序生命周期_1

为什么asp.net落后了,还讲这些?因为mvc 还是沿用老框架的,加了一个请求模块,在第七个事件中触发; 一.概念 HTTP模块(HttpModule)是通过实现IHttpModule接口和处理事件,在每次针对应用程序发出请求时调用的程序集.HTTP模块作为ASP.NET请求管线的一部分调用,能够在整个请求过程中访问生命周期事件.因此,HTTP模块使我们有机会检查传入和传出的请求,并根据该请求采取操作,甚至我们可以通过实现HTTP模块来参与ASP.NET的运行管理. 二.托管管道模式(IIS应

Linux、Windows网络工程师面试题精选

1.请你修改一下LINUX的视频驱动和声音驱动? 答: redhatlinux中用sndconfig来设置声卡,如果没有某个模块,就需要重新编译内核(编译最新发布的linux 内核),如果还不行,只好用ALSA 音效驱动程式. Redhat-config- xfree86 答: 命令行下etc/X11/XF86config 2.如何修改LINUX的启动速度? 答.运行级别设为3 2.chkconfig从中可以关掉一些不需要的服务,如sendmail 3.如何取消APACHE的目录索引 ? Apa

Linux面试题(1)

一.填空题: 1. 在Linux系统中,以 文件 方式访问设备 . 2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的文件系统. 3. Linux文件系统中每个文件用 i节点 来标识. 4. 全部磁盘块由四个部分组成,分别为引导块 .专用块 . i节点表块 和数据存储块. 5. 链接分为: 硬链接 和 符号链接 . 6. 超级块包含了i节点表 和 空闲块表 等重要的文件系统信息. 7. 某文件的权限为:d-rw-_r--_r--,用数值形式表示该权限,则该八进制数为: 64