我有一些HTML,例如:
<%@ Page Title="About Us" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="ContentManagedTargetPage.aspx.cs" Inherits="xxx.ContentManagedTargetPage" %>
<%@ Register TagPrefix="CxCMS" Namespace="xxx.ContentManagement.ASPNET.UI" Assembly="xxx.ContentManagement.ASPNET" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Content Managed
</h2>
<p>
Put content here.
[<CxCMS:ContentManagedPlaceHolder Key="keyThingy" runat="server" />]
</p>
</asp:Content>
我想找到CxCMS的所有实例:ContentManagedPlaceHolder元素。
我正在使用HTML Agility Pack,这似乎是最合适的。
然而,尽管查看[微薄]文档,但我无法使用我的代码。
我希望以下方法有效:
string searchForElement = "CxCMS:ContentManagedPlaceHolder";
IEnumerable<HtmlNode> contentPlaceHolderHtmlNodes = HtmlDocument.DocumentNode.Descendants(searchForElement);
int count = contentPlaceHolderHtmlNodes.Count();
但我一无所获。
如果我更改为DescendantsOrSelf,我会返回文档节点“#document” - 这是不正确的:
string searchForElement = "CxCMS:ContentManagedPlaceHolder";
IEnumerable<HtmlNode> contentPlaceHolderHtmlNodes = HtmlDocument.DocumentNode.DescendantsOrSelf(searchForElement);
int count = contentPlaceHolderHtmlNodes.Count();
我也尝试过使用LINQ:
string searchForElement = "CxCMS:ContentManagedPlaceHolder";
IEnumerable<HtmlNode> contentPlaceHolderHtmlNodes = HtmlDocument.DocumentNode.DescendantsOrSelf().Where(q=>q.Name==searchForElement);
int count = contentPlaceHolderHtmlNodes.Count();
由于这两种方法都不起作用,我转而使用SelectNodes,而不是:
string searchForElement = "CxCMS:ContentManagedPlaceHolder";
string xPath="//"+searchForElement // "//CxCMS:ContentManagedPlaceHolder"
var nodes= HtmlDocument.DocumentNode.SelectNodes(xPath);
这只会引发异常:“需要命名空间管理器或XsltContext。此查询具有前缀,变量或用户定义的函数。”我找不到向HtmlDocument对象添加命名空间管理的任何方法。
我想念的是什么? DescendantsOrSelf()方法在使用“标准”HTML标记时起作用,例如“p”,但不是我拥有的标记。当然应该有用吗? (它需要!)
答案 0 :(得分:1)
像往常一样,我花了一个小时左右的时间玩,我问这个问题,并在几秒钟之后弄明白。
使用DescendantsOrSelf()进行搜索时,节点名称必须为小写。
答案 1 :(得分:0)
您的示例实际上是ASPX。如果您正在解析该页面的输出,那么<CxCMS:ContentManagedPlaceHolder Key="keyThingy" runat="server" />
实际呈现为客户端上的内容是值得怀疑的。查看客户端上的html源代码,找到与<CxCMS:ContentManagedPlaceHolder Key="keyThingy" runat="server" />
对应的输出代码,然后在HtmlDocument.DocumentNode.Descendants
中使用这些代码。
另一方面,如果您正在解析ASPX源代码,则可能需要将输入调整为HtmlDocument.DocumentNode.Descendants
以便HtmlAgilityPack识别它,但请记住ASPX!= html并且我不知道我认为构建HtmlAgilityPack是为了解析它。
编辑:在HtmlAgilityPack源代码中查看HtmlNode.cs,由于以下两个部分,看起来你需要小写是正确的:
/// <summary>
/// Gets or sets this node's name.
/// </summary>
public string Name
{
get
{
if (_name == null)
{
Name = _ownerdocument._text
.Substring(_namestartindex, _namelength);
}
return _name != null ? _name.ToLower() : string.Empty;
}
set { _name = value; }
}
和
/// <summary>
/// Get all descendant nodes with matching name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IEnumerable<HtmlNode> Descendants(string name)
{
foreach (HtmlNode node in Descendants())
if (node.Name == name)
yield return node;
}
请注意_name.ToLower()
的getter中的Name
和if (node.Name == name)
方法中区分大小写的Decendants
。这与使用DescendantsAndSelf
,Element
和Elements
方法的检查相同。