将HTML转成XHTML并清除一些无用的标签和属性
介绍
这是一个能帮你从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   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( "'", "'" ); text = text.Replace( "\"", ""e;" ); if( this.FilterOutput ) { text = text.Trim(); // We want to replace consecutive spaces // to one space in order to save horizontal width if( this.ReduceConsecutiveSpace ) text = text.Replace(" ", " "); if( this.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){ if( this.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 attributeif( 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并清除一些无用的标签和属性的更多相关文章
- C#怎么清除字符串中HTML标签。。。
因为用到了一款编辑器的原因,使得数据库中保存的数据会夹杂着一些HTML标签,之后导出的数据中就会出现一些不同的HTML的标签.严重影响用户的视觉体验(主要自己都看不下去了)... 下面是我将DataT ...
- js 写成类的形式 js 静态变量 js方法 属性 json类
function ClassStudentList() { //[{"Cid":"0d","Students":[{"Sid&qu ...
- 清除li内a标签的float=left实现a标签在li内居中显示(ul内li不居中显示)
写在前面: 修改cnblogs主页面菜单显示问题. 问题描述:在给主菜单添加hover样式后发现菜单内容并未居中.见图1. 网上搜索到资料其中一篇讲的可以说简明扼要了,也是伸手党的福利(点我查看原文) ...
- 清除浏览器缓存meta标签
<meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv ...
- Code Project精彩系列(转)
Code Project精彩系列(转) Code Project精彩系列(转) Applications Crafting a C# forms Editor From scratch htt ...
- NEC的学习笔记
写过很多代码后,会有代码的规范有一些需求,会有想写出美观.规范.易懂的代码. 今天学习了NEC,全称Nice Easy CSS(http://nec.netease.com/),顾名思义,就是为了写简 ...
- JavaWeb(HTML +css+js+Servlet....)
注意 1.不要把函数命名为add(),不然容易和自带的冲突报错 2.是createElement 不要把create中的e写掉了 3.记得是getElementsByTaxName和getElemen ...
- js的DOM对象
1.js的Array对象 ** 创建数组(三种) - var arr1 = [1,2,3]; ...
- Javaweb之JavaScript结合(二)
1.js的String对象 ** 创建String对象 *** var str = "abc"; ** 方法和属性(文档) *** 属性 length:字符串的长度 *** 方法 ...
随机推荐
- tcp,第一个例子,客户端,服务端
1.客户端 package cd.itcast.xieyi; import java.io.IOException; import java.io.OutputStream; import java. ...
- 15.python的for循环与迭代器、生成器
在前面学习讲完while循环之后,现在终于要将for循环这个坑填上了.之所以拖到现在是因为for循环对前面讲过的序列.字典.集合都是有效的,讲完前面的内容再来讲for循环会更加容易上手. 首先,for ...
- 1.html5究竟是什么
1.html5的起源,历史背景…… 按照一般的套路,我这里应该对html5的起源和发展历史,其优越性等大书特书一番.但既然你有意识地专门去找类似的文章,说明你早有相应的认识,就算没有,类似的东西网上也 ...
- python解析页面上json字段
一般来说,当我们从一个网页上拿下来数据,就是一个字符串,比如: url_data = urllib2.urlopen(url).readline() 当我们这样得到页面数据,url_data是全部页面 ...
- C 关于二叉查找树的回顾,并简述结构接口设计
前言 最经想改写C用的配置读取接口, 准备采用hash或二叉树提到原先用的链表,提高查找效率.就回顾一下二叉树,这里分享一下二叉查找树,代码很精简的, 适合学习运用二叉树查找. 需要基础 1.具备C ...
- 菜鸟学习Hibernate——缓存
Hibernate的缓存分为三种:一级缓存.二级缓存.查询缓存.下面我就为大家介绍一下. 一.概念. 一级缓存:第一级存放于session中称为一级缓存.Session 级别的缓存,它同session ...
- java下的redis操作
Java操作redis(增删改查) Java代码 package sgh.main.powersite; import java.util.ArrayList; import java.util.Ha ...
- SQLite数据库与Contentprovider(2)
ContentProvider: 在创建ContentProvider时,需要首先使用数据库.文件系统或网络实现底层存储功能, 然后在继承ContentProvider的类中实现基本数据操作的接口函数 ...
- Ubuntu 修改用户密码与启动root账号
passwd sban 修改当前帐号 sudo passwd root 修改root帐号 修改/etc/ssh/sshd_config,改: PermitRootLogin without-passw ...
- linux 捕获信号处理中遇到的死锁
tag: 信号 signal sigchld 死锁 堆栈 我们的程序需要捕获信号自己处理,所以尝试对1-32的信号处理(后面33-64的信号不处理).但是在调试代码时,发现一个线程死锁的问题.程序 ...