介绍

  这是一个能帮你从HTML生成有效XHTML的经典库。它还提供对标签以及属性过滤的支持。你可以指定允许哪些标签和属性可在出现在输出中,而其他的标签过滤掉。你也可以使用这个库清理Microsoft Word文档转化成HTML时生成的臃肿的HTML。你也在将HTML发布到博客网站前清理一下,否则像WordPress、b2evolution等博客引擎会拒绝的。

 它是如何工作的

  里面有两个类:HtmlReader和HtmlWriter

  HtmlReader拓展了著名的由Chris Clovett开发的SgmlReader。当它读取HTML时,它跳过所有有前缀的节点。其中,所有像<o:p>、<o:Document>、<st1:personname>等上百的无用标签被滤除了。这样你读取的HTML就剩下核心的HTML标签了。

  HtmlWriter拓展了常规的XmlWriter,XmlWriter生成XML。XHTML本质上是XML格式的HTML。所有你熟悉使用的标签——比如<img>、<br>和<hr>,都不是闭合的标签——在XHTML中必需是空元素形式,像<img .. />、<br/>和<hr/>。由于XHTML是常见的XML格式,你可以方便的使用XML解析器读取XHTML文档。这使得有了应用XPath搜索的机会。

 HtmlReader

  HtmlReader很简单,下面是完整的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
////// This class skips all nodes which has some
/// kind of prefix. This trick does the job 
/// to clean up MS Word/Outlook HTML markups.
///public class HtmlReader : Sgml.SgmlReader
{
    public HtmlReader( TextReader reader ) : base( )
    {
        base.InputStream = reader;
        base.DocType = "HTML";
    }
    public HtmlReader( string content ) : base( )
    {
        base.InputStream = new StringReader( content );
        base.DocType = "HTML";
    }
    public override bool Read()
    {
        bool status = base.Read();
        if( status )
        {
            if( base.NodeType == XmlNodeType.Element )
            {
                // Got a node with prefix. This must be one
                // of those "" or something else.
                // Skip this node entirely. We want prefix
                // less nodes so that the resultant XML 
                // requires not namespace.
                if( base.Name.IndexOf(':') > 0 )
                    base.Skip();
            }
        }
        return status;
    }
}

 HtmlWriter

  这个类是有点麻烦。下面是使用技巧:

  • 重写WriteString方法并避免使用常规的XML编码。对HTML文件手动更改编码。

  • 重写WriteStartElementis以避免不被允许的标签写到输出中。

  • 重写WriteAttributesis以避免不需求的属性。

  让我们分部分来看下整个类:

  可配置性

  你可以通过修改下面的部分配置HtmlWriter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class HtmlWriter : XmlTextWriter
{
    ////// If set to true, it will filter the output
    /// by using tag and attribute filtering,
    /// space reduce etc
    ///public bool FilterOutput = false;
    ////// If true, it will reduce consecutive   with one instance
    ///public bool ReduceConsecutiveSpace = true;
    ////// Set the tag names in lower case which are allowed to go to output
    ///public string [] AllowedTags = 
        new string[] { "p""b""i""u""em""big""small"
        "div""img""span""blockquote""code""pre""br""hr"
        "ul""ol""li""del""ins""strong""a""font""dd""dt"};
    ////// If any tag found which is not allowed, it is replaced by this tag.
    /// Specify a tag which has least impact on output
    ///public string ReplacementTag = "dd";
    ////// New lines \r\n are replaced with space 
    /// which saves space and makes the
    /// output compact
    ///public bool RemoveNewlines = true;
    ////// Specify which attributes are allowed. 
    /// Any other attribute will be discarded
    ///public string [] AllowedAttributes = new string[] 
    
        "class""href""target""border""src"
        "align""width""height""color""size" 
    };
}

  WriteString方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
////// The reason why we are overriding
/// this method is, we do not want the output to be
/// encoded for texts inside attribute
/// and inside node elements. For example, all the  
/// gets converted to &nbsp in output. But this does not 
/// apply to HTML. In HTML, we need to have   as it is.
//////public override void WriteString(string text)
{
    // Change all non-breaking space to normal space
    text = text.Replace( " "" " );
    /// When you are reading RSS feed and writing Html, 
    /// this line helps remove those CDATA tags
    text = text.Replace("""");
 
    // Do some encoding of our own because
    // we are going to use WriteRaw which won't
    // do any of the necessary encoding
    text = text.Replace( "<""<" );
    text = text.Replace( ">"">" );
    text = text.Replace( "'""&apos;" );
    text = text.Replace( "\""""e;" );
 
    ifthis.FilterOutput )
    {
        text = text.Trim();
 
        // We want to replace consecutive spaces
        // to one space in order to save horizontal width
        ifthis.ReduceConsecutiveSpace ) 
            text = text.Replace("   "" ");
        ifthis.RemoveNewlines ) 
            text = text.Replace(Environment.NewLine, " ");
 
        base.WriteRaw( text );
    }
    else
    {
        base.WriteRaw( text );
    }
}

  WriteStartElement: 应用标签过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public override void WriteStartElement(string prefix, 
    string localName, string ns)
{
    ifthis.FilterOutput ) 
    {
        bool canWrite = false;
        string tagLocalName = localName.ToLower();
        foreach( string name in this.AllowedTags )
        {
            if( name == tagLocalName )
            {
                canWrite = true;
                break;
            }
        }
        if( !canWrite ) 
        localName = "dd";
    }
    base.WriteStartElement(prefix, localName, ns);
}

  WriteAttributes方法: 应用属性过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool canWrite = false;
string attributeLocalName = reader.LocalName.ToLower();
foreach( string name in this.AllowedAttributes )
{
    if( name == attributeLocalName )
    {
        canWrite = true;
        break;
    }
}
// If allowed, write the attribute
if( canWrite ) 
    this.WriteStartAttribute(reader.Prefix, 
    attributeLocalName, reader.NamespaceURI);
while (reader.ReadAttributeValue())
{
    if (reader.NodeType == XmlNodeType.EntityReference)
    {
        if( canWrite ) this.WriteEntityRef(reader.Name);
        continue;
    }
    if( canWrite )this.WriteString(reader.Value);
}
if( canWrite ) this.WriteEndAttribute();

 结论

  示例应用是一个你可以立即用来清理HTML文件的实用工具。你可以将这个类应用在像博客等需要发布一些HTML到Web服务的工具中。

  原文地址:http://www.codeproject.com/Articles/10792/Convert-HTML-to-XHTML-and-Clean-Unnecessary-Tags-a

将HTML转成XHTML并清除一些无用的标签和属性的更多相关文章

  1. C#怎么清除字符串中HTML标签。。。

    因为用到了一款编辑器的原因,使得数据库中保存的数据会夹杂着一些HTML标签,之后导出的数据中就会出现一些不同的HTML的标签.严重影响用户的视觉体验(主要自己都看不下去了)... 下面是我将DataT ...

  2. js 写成类的形式 js 静态变量 js方法 属性 json类

    function ClassStudentList() { //[{"Cid":"0d","Students":[{"Sid&qu ...

  3. 清除li内a标签的float=left实现a标签在li内居中显示(ul内li不居中显示)

    写在前面: 修改cnblogs主页面菜单显示问题. 问题描述:在给主菜单添加hover样式后发现菜单内容并未居中.见图1. 网上搜索到资料其中一篇讲的可以说简明扼要了,也是伸手党的福利(点我查看原文) ...

  4. 清除浏览器缓存meta标签

    <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv ...

  5. Code Project精彩系列(转)

    Code Project精彩系列(转)   Code Project精彩系列(转)   Applications Crafting a C# forms Editor From scratch htt ...

  6. NEC的学习笔记

    写过很多代码后,会有代码的规范有一些需求,会有想写出美观.规范.易懂的代码. 今天学习了NEC,全称Nice Easy CSS(http://nec.netease.com/),顾名思义,就是为了写简 ...

  7. JavaWeb(HTML +css+js+Servlet....)

    注意 1.不要把函数命名为add(),不然容易和自带的冲突报错 2.是createElement 不要把create中的e写掉了 3.记得是getElementsByTaxName和getElemen ...

  8. js的DOM对象

    1.js的Array对象           ** 创建数组(三种)                          - var arr1 = [1,2,3];                    ...

  9. Javaweb之JavaScript结合(二)

    1.js的String对象 ** 创建String对象 *** var str = "abc"; ** 方法和属性(文档) *** 属性 length:字符串的长度 *** 方法 ...

随机推荐

  1. Ghost命令使用方法

    我们知道,一般使用Ghost时,都是在DOS提示符后先键入"Ghost",然后再进入Ghost的图形界面操作:那么可不可以让Ghost也只通过命令行的方式工作呢?答案是肯定的,在键 ...

  2. 利用HttpWebRequest访问WebApi

    WebApi现在越来越流行,下面给出利用HttpWebRequest访问WebApi的工具方法: 1.利用基准URL和参数字典生成完整URL /// <summary> /// 生成URL ...

  3. 实战Django:官方实例Part2

    我们接着Part1部分往下讲.我们在part1中启动服务器后,并没有在管理页面中发现新添加的Polls应用,怎么办捏? 7.在管理界面中显示Question 只要注册一下这个应用就可以了.编辑poll ...

  4. ruby on rails 实战(一)

    通过ruby on rails 一步一步搭建个人站点,涉及到的技术有:ruby,rails,javascript,jquery 操作系统:win7 IDE: rubymine 5.4. 第一步,下载安 ...

  5. 成长记录 if语句输出 由大到小的数字

    #include<stdio.h> void main() { float a,b,c,d,e,f,g,t; scanf("%f,%f,%f,%f,%f,%f,%f", ...

  6. 使用Apriori算法和FP-growth算法进行关联分析

    系列文章:<机器学习实战>学习笔记 最近看了<机器学习实战>中的第11章(使用Apriori算法进行关联分析)和第12章(使用FP-growth算法来高效发现频繁项集).正如章 ...

  7. 史上最佳 Mac+PhpStorm+XAMPP+Xdebug 集成开发和断点调试环境的配置

    在上一篇 PHP 系列的文章<PHP 集成开发环境比较>中,我根据自己的亲身体验,非常简略的介绍和对比了几款常用的集成开发环境,就我个人而言,比较推崇 Zend Studio 和 PhpS ...

  8. iOS耳机操作

    iOS在7之后增加的麦克风权限的申请,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 AVAudioSession *avSession = [AVAudioSession shar ...

  9. iis7应用程序池自动关闭问题解决

    解决: 应用程序池启动32位应用程序 设置托管管道为集成 (仍然有问题) 图片:123.png 访问网站之前 应用程序池是开启的 访问后 网页报503 service unavailable应用程序池 ...

  10. Python实现SVM(支持向量机)

    Python实现SVM(支持向量机) 运行环境 Pyhton3 numpy(科学计算包) matplotlib(画图所需,不画图可不必) 计算过程 st=>start: 开始 e=>end ...