Html Agility Pack: DescendantsOrSelf () не возвращает элемент HTML - PullRequest
0 голосов
/ 16 июня 2010

У меня есть некоторый 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);

Это просто вызывает исключение: "Namespace Manager или XsltContext необходимы. Этозапрос имеет префикс, переменную или пользовательскую функцию. "Я не могу найти способ добавить управление пространством имен к объекту HtmlDocument.

Чего мне здесь не хватает?Метод DescendantsOrSelf () работает, если используется «стандартный» тег HTML, такой как «p», но не тот, который у меня есть.Конечно, это должно работать?(Это нужно!)

Ответы [ 2 ]

1 голос
/ 16 июня 2010

Как обычно, я провожу час или около того, играя, я задаю вопрос и выясняю его через несколько секунд.

При поиске с использованием DescendantsOrSelf () имя узла должно быть в нижнем регистре.

0 голосов
/ 16 июня 2010

Ваш пример на самом деле 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 создан для его анализа.

Редактировать: Просматривая файл HtmlNode.cs в исходном коде HtmlAgilityPack, кажется, что вы правы в том, что он должен быть в нижнем регистре из-за следующих двух разделов:

    /// <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() в получателе для Name и на регистр if (node.Name == name) в методе Decendants. Это та же проверка, что и для методов DescendantsAndSelf, Element и Elements.

...