考虑以下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中是否有办法获取此信息?
答案 0 :(得分:3)
我最终修改了HtmlAgilityPack的代码,以公开一个返回_outerlength
的私有HtmlNode
字段的新属性。
public virtual int OuterLength
{
get
{
return ( _outerlength );
}
}
到目前为止,这似乎工作正常。
答案 1 :(得分:2)
如果要在不重新编译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);
答案 2 :(得分:1)
将@Xcalibur的答案转换为扩展方法。
请注意,HtmlNode
具有属性OuterLength
,但它与私有字段_outerlength
不同,这正是我们所需要的。 (在这里阅读其他答案,我首先想到,自2013年以来,HtmlAgilityPack已将OuterLength
作为公共属性添加,他们这样做了,但是经过一些测试,我注意到它只是返回了OuterHtml
的长度)。因此,我们可以从源头重建程序包以将字段公开为公共属性,也可以使用带有Reflection的扩展方法(速度很慢)。
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()