zoukankan      html  css  js  c++  java
  • 将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   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

  • 相关阅读:
    提权函数之RtlAdjustPrivilege()
    用C#写外挂或辅助工具必须要的WindowsAPI
    ASP.net中保持页面中滚动条状态
    asp.net窗体的打开和关闭
    界面原型设计工具 Balsamiq Mockups
    在List(T)中查找数据的两种方法
    P2158 [SDOI2008]仪仗队 题解
    P1531 I Hate It 题解
    C#
    破解网站防盗链
  • 原文地址:https://www.cnblogs.com/ranzige/p/4365579.html
Copyright © 2011-2022 走看看