3

考虑以下 HTML 片段(_用于空格):

<head>
    ...
    <link ... ___/>
    <!-- ... -->
    ...
</head>

我正在使用 Html Agility Pack (HAP) 来读取 HTML 文件/片段并去除链接。我想要做的是找到LINK(和其他一些)元素,然后用空格替换它们,如下所示:

<head>
    ...
    ____________
    <!-- ... -->
    ...
</head>

到目前为止,解析部分似乎正在工作,我得到了我正在寻找的节点。但是,HAP 会尝试修复 HTML 内容,而我需要所有内容完全相同,除了我正在尝试进行的更改。另外,在回写之前读入的内容时,HAP 似乎有很多错误,所以我想采取的方法是让 HAP 解析输入,然后我回到原始输入并替换我的内容不想要。

问题是,HtmlNode似乎没有输入长度属性。它StreamPosition似乎表明在输入中开始读取节点内容的位置,但我找不到可以告诉我构建节点消耗了多少字符的长度属性。

我尝试使用该OuterHtml属性,但不幸的是,HAP 尝试LINK通过删除该___/部分来修复该属性(LINK不应该关闭一个元素)。因此,OuterHtml.Length返回错误的长度。

HAP 有没有办法获取这些信息?

4

3 回答 3

3

我最终修改了 HtmlAgilityPack 的代码以公开一个新属性,该属性_outerlength返回HtmlNode.

public virtual int OuterLength
{
    get
    {
        return ( _outerlength );
    }
}

到目前为止,这似乎工作正常。

于 2012-10-24T03:36:00.903 回答
3

如果您想在不重新编译 HAP 的情况下获得相同的结果,请使用反射来访问私有变量。

我通常不建议使用反射来访问私有变量,但我最近遇到了与此完全相同的情况并使用了反射,因为我无法使用程序集的重新编译版本。为此,请创建一个包含字段信息对象的静态变量(以避免在每次使用时重新创建它):

private static readonly FieldInfo HtmlNodeOuterLengthFieldInfo = typeof(HtmlNode).GetField("_outerlength", BindingFlags.NonPublic | BindingFlags.Instance);

然后,每当您想访问原始外部 HTML 的真实长度时:

var match = htmlDocument.DocumentNode.SelectSingleNode("xpath");
var htmlLength = (int)HtmlNodeOuterLengthFieldInfo.GetValue(match);
于 2013-03-10T13:29:12.367 回答
1

将@Xcalibur 的答案转换为扩展方法。

请注意,它HtmlNode有 property OuterLength,但它与它的 private field 不同_outerlength,这是我们需要的。(在这里阅读其他答案时,我首先认为自 2013 年以来,HtmlAgilityPack 已经将其添加OuterLength为公共属性,他们确实这样做了,但经过一些测试,我注意到它只是返回 length of OuterHtml)。因此,我们可以从源代码重建包以将字段公开为公共属性,或者使用带有反射的扩展方法(这很慢)。

扩展方法

namespace HtmlAgilityPack
{
    public static class HtmlDocumentExtensions
    {
        private static readonly System.Reflection.FieldInfo HtmlNodeOuterLengthFieldInfo = 
          typeof(HtmlNode).GetField("_outerlength", System.Reflection.BindingFlags.NonPublic 
          | System.Reflection.BindingFlags.Instance);

        public static int GetOuterLengthInStream(this HtmlNode node) => 
          (int)HtmlNodeOuterLengthFieldInfo.GetValue(node ?? 
          throw new System.ArgumentNullException(nameof(node)));
    }
}

因为HtmlNode已经有了属性OuterLength,为了避免歧义我调用了方法GetOuterLengthInStream()

用法

node.GetOuterLengthInStream()
于 2020-05-18T22:04:29.967 回答