热搜:NVER node 开发 php

将HTML转成XHTML并清除一些无用的标签和属性_html/css_WEB-ITnose

2024-11-10 23:00:01
将HTML转成XHTML并清除一些无用的标签和属性_html/css_WEB-ITnose

介绍

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

 它是如何工作的

  里面有两个类:HtmlReader和HtmlWriter

  HtmlReader拓展了著名的由Chris Clovett开发的SgmlReader。当它读取HTML时,它跳过所有有前缀的节点。其中,所有像

等上百的无用标签被滤除了。这样你读取的HTML就剩下核心的HTML标签了。

  HtmlWriter拓展了常规的XmlWriter,XmlWriter生成XML。XHTML本质上是XML格式的HTML。所有你熟悉使用的标签??比如、


,都不是闭合的标签??在XHTML中必需是空元素形式,像、

。由于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(  "'" ,  "'"  );

         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 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服务的工具中。