使用Html Agility Pack

时间:2015-07-07 11:12:43

标签: c# html-parsing html-agility-pack

我有一个Html字符串,它包含各种Html但包含此

<span style="display:block;position:fixed;width:100%;height:2000px;background-color:rgba(0,0,0,0);z-index:9999!important;top:0;left:0;cursor:default;"></span>

这看起来很奇怪,但我只想删除style属性中的特定项(对于所有Html元素)。例如,我想删除

position:fixedz-index:9999!important;以及top:0;left:0;

仅举几例,但保留其他所有内容。现在的问题是,它不一定是position:fixed;它可能是position:absolute;或其他什么。就像它可能是z-index:9998;top:20;等......

我需要能够按键移除样式元素,因此position:*anything*top:*anything*等等。并且还以非大小写敏感的方式执行此操作。因此它会获得POSITION:*anything*PoSition:*anything*

有没有办法使用Html Agility Pack实现这一目标?

5 个答案:

答案 0 :(得分:3)

在HTML Agility Pack中似乎没有对内联样式字符串解析的任何支持,但.NET在System.Web.UI中确实具有一些支持WebForms控件的功能。

它被称为CssStyleCollection,它会将您的style字符串转换为一个很好的字符串键/值对数组,并允许您删除不需要的特定键

但是,由于它是WebControl使用的内部工具,因此它没有公共构造函数。相反,你必须通过反射来实例化它,或者使用像这样的黑客;

CssStyleCollection style = new Panel().Style;

创建后,

style.Value = "YOUR STYLE STRING"; 

然后删除您不想要的内容;

style.Remove("position");
style.Remove("z-index");
style.Remove("top");
style.Remove("left");

style.Value检索新的分隔样式字符串。

重要提示:我还没有对此进行测试,但这个过程看起来很简单,如果有点hacky。我可能还会遇到一些惊喜。特别是,我不知道它如何处理同一个字符串中有多个重复样式设置的情况;

top:0;margin-left:20;top:10; 

在内联样式字符串中,浏览器将遵循最后指定的值,因此top:10获胜。但是,由于CssStyleCollection使用唯一键,因此无法同时存储top个值,也很可能会丢弃一个。

答案 1 :(得分:1)

我认为你只需要使用HAP来抓取你要清理的元素,从属性中获取样式然后循环它们以手动清理它们。

我分开&#34;;&#34;那么&#34;:&#34;获取名称/值对。循环遍历它们,将名称小写并将其放入switch语句中,以便于使用它们,并使用默认值将名称/值附加到新字符串。然后将新的样式字符串注入您的属性。

 // Psuedo code, not the real deal!!
 // Inspired from http://htmlagilitypack.codeplex.com/wikipage?title=Examples
 HtmlDocument doc = new HtmlDocument(); 

 doc.Load("file.htm");
 foreach(HtmlNode span in doc.DocumentElement.SelectNodes("//span[@style]"))
 {
    HtmlAttribute att = span["style"];
    att.Value = CleanStyles(att.Value);
 }
 doc.Save("file.htm");

 // Elsewhere
 public string CleanStyles( string oldStyles ) {
    string newStyles = "";
    foreach( var entries in oldStyle.Split( ';' ) ) {
       var values = entries.Split(':');
       switch( values[0].ToLower() ) {
          case "position":
          case "z-index":
            // Do nothing, skip this value
            break;
          default:
             newStyles += values.Join(':') + ";";
       }
    }  
    return newStyles;
 }

无论如何都是这样的。

答案 2 :(得分:0)

使用HTML包和正则表达式。在之前匹配名称:选择文本之后:直到下一个;应该给你一系列的职位?然后从字符串中删除那些位置?希望有道理:)

你可以按照上面的方式进行,但我会变得混乱。如果可能,请使用正则表达式:)

答案 3 :(得分:0)

在HAP中有一种非常简单的编辑样式属性的方法,如以下示例所示: https://html-agility-pack.net/knowledge-base/12062495/better-way-to-add-a-style-attribute-to-html-using-htmlagilitypack

const string margin = "margin-top: 0";
foreach (var pTagNode in pTagNodes)
{
    var styles = pTagNode.GetAttributeValue("style", null);
    var separator = (styles == null ? null : "; ");
    pTagNode.SetAttributeValue("style", styles + separator + margin);
}

答案 4 :(得分:0)

我的解决方案是删除样式属性中的旧元素,然后可以添加所需的另一个元素。 我有例子:

<span style="font-size:12pt;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:Arial;lang:EN-US;mso-fareast-language:EN-US;mso-ansi-language:AR-SA;">&nbsp;</span>

我要删除font-family:Calibri;。您可以看到style属性中的每个元素都由“;”分隔。因此,您只需找到所需属性的索引和“;”索引之后最接近的。删除它并添加或不添加任何东西。

我的示例代码删除元素font-family:Calibri并添加font-family:Time新罗马字是:

foreach (HtmlAgilityPack.HtmlNode span in doc.DocumentNode.SelectNodes("//span[@style]"))
{
    HtmlAgilityPack.HtmlAttribute att = span.Attributes["style"];
    att.Value = ChageFontFamily(att.Value);        
}

private string ChageFontFamily(string value)
{
    //Get index of element you want to remove.
    //Get index of ";" neareast to remove.
    var idxStart = value.IndexOf("font-family:");
    var idxEnd = value.IndexOf(";", idxStart);

    //remove it
    value = value.Remove(idxStart, idxEnd - idxStart + 1);

    //you can add other element like this and return it
    value += "font-family:Time New Roman;";
    return value;
}

那是我的解决方案。享受吧!