0

我有一些 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,这似乎是最合适的。

但是,尽管查看了 [meagre] 文档,但我无法让我的代码正常工作。

我希望以下工作:

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”)时有效,但不是我拥有的标签。当然它应该工作?(它需要!)

4

2 回答 2

1

像往常一样,我花了一个小时左右的时间玩,我问这个问题,几秒钟后我就弄清楚了。

使用 DescendantsOrSelf() 搜索时,节点名称必须小写。

于 2010-06-16T17:26:21.907 回答
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 for 中的Name,以及方法中区分大小写if (node.Name == name)Decendants。这与使用DescendantsAndSelf,ElementElements方法的检查相同。

于 2010-06-16T17:26:45.910 回答