开发者

HtmlAgilityPack: How to interpret non-tag-ed text in HTML

开发者 https://www.devze.com 2023-03-15 16:49 出处:网络
Know that the title is kind of vague, here is an example, <DIV> <DIV>title1</DIV> line1<br/>

Know that the title is kind of vague, here is an example,

<DIV>
 <DIV>title1</DIV>
 line1<br/>
 line2<br/>
 <DIV>title2</DIV>
 line2.1<br/>
 line2.2<br/>
</DIV>

How can I fetch line1<br/>line2<br/> for title1, and line2.1<br/>line2.2<br/> for title2? I'm using HtmlAgilityPack and SharpQuery together.

Thanks.

Possible Resolution

After researched and tried more, I managed to fetch these by using LinePosition and "//div/text()"

public static HtmlNodeCollection getNodes(string html, string xpath)
{
    if (html.Length <= 0) { return null; }
    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(html);
    return doc.DocumentNode.SelectNodes(xpath);
}

foreach (HtmlNode node in getNodes(html, "//div"){
    foreach (HtmlNode plain_node in getNodes(html, "//div/text()")
    {
        if (plain_node.LinePosition <= node开发者_运维问答.LinePosition)
        {
            currentHtml += plain_n.InnerHtml + "<br/>";
        }
    }
}

Any other better way?


There is rarely one unique solution to an html matching problem. Although your solution works fine now and with your sample, the //div expression will search all div elements under root, recursively.

It means if the original Html evolves somehow, you may catch too many things or analyze too many nodes (performance may be an issue with things like // for big documents).

I would suggest something like this, which is more discriminant:

        HtmlDocument doc = new HtmlDocument();
        doc.Load(yourHtmlFile);

        foreach (HtmlNode node in doc.DocumentNode.SelectNodes("/div/div[starts-with(text(), 'title')]/following-sibling::text()[normalize-space(.) != '']"))
        {
            Console.WriteLine(node.InnerText.Trim());
        }

It means

  • Search div elements from the root
  • Then search div elements underneath
  • Filter (using [...]) these elements and only select those with an inner text that start with 'title'
  • Then search all following sibling elements of type text
  • Filter these elements and only select those which are not empty or whitespace only

See this link for some help on XPATH Axes.


Assuming the structure is always the same you could get the divs and then get both of their NextSiblings

0

精彩评论

暂无评论...
验证码 换一张
取 消