3

我正在尝试解析特定的 HTML 字符串,以便我可以提取一组由<br/>换行符分隔的行。输入 HTML 如下所示:

<div class="PlainText">
  DATE: 2013-10-28 20:00:43 -0500 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  <br/> //Notice this has two break lines, i would like to stop after seeing two consecutive break lines.
</div>

使用更大的 html 文档中的这个 div,我能够得到HTML ChildNodes

List<HtmlNode> nodes = htmlDoc.DocumentNode
                                    .Descendants("div")
                                    .Where(x => x.Attributes.Contains("class") &&
                                            x.Attributes["class"].Value.Contains("PlainText")).ToList();

我不完全确定从这里去哪里,我想阅读所有文本,直到我看到两条断线并停止?

编辑

我查看了nodesVisual Studio 运行时检查器中的 childNodes 并注意到实际上没有两条连续<br/>的线,而是一条断线和一个#text标签,其 innerHTMl 是\n一个换行符。

在此处输入图像描述

4

2 回答 2

1

您可以使用 XPath//div[@class='PlainText']获取所需的 div 节点。您还可以在从 div 获取子节点时检查下一个兄弟节点:

HtmlDocument doc = new HtmlDocument();
doc.Load("index.html");
Func<HtmlNode, bool> notTwoBrakes = 
    n => (n.Name != "br" || n.NextSibling != null && n.NextSibling.Name != "br");
var nodes = doc.DocumentNode.SelectNodes("//div[@class='PlainText']")
               .Select(div => div.ChildNodes.TakeWhile(notTwoBrakes));

我不只是为了可读性而使用内联 lambda。条件是这样工作的:

  • 检查下一个节点是否为空,如果为空,则取当前节点
  • 检查下一个节点是否是br节点,如果不是 - 取当前节点
  • 检查当前节点是否为br节点,如果不是 - 取当前节点
  • 否则停止获取子节点

结果:

在此处输入图像描述

于 2013-10-31T16:08:15.490 回答
0

像这样的东西应该工作

[Test]
public void Test()
{
    var x = ReadTillTwoBr(GetDivClass()).ToList();
}

public HtmlNode GetDivClass()
{
    var html = @"<html><div class=""PlainText"">
            DATE: 2013-10-28 20:00:43 -0500 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            <br   /> //Notice this has two break lines, i would like to stop after seeing two consecutive break lines.
            Item 3
        </div></html>";
    var doc = new HtmlDocument();
    doc.LoadHtml(html);

    return doc.DocumentNode
                .Descendants("div").First(x => x.Attributes.Contains("class") &&
                                                x.Attributes["class"].Value.Contains("PlainText"));

}

public IEnumerable<string> ReadTillTwoBr(HtmlNode node)
{
    var nonEmptyNodes =
        node.ChildNodes.Except(node.ChildNodes.Where(f => f.Name == "#text" && String.IsNullOrWhiteSpace(f.InnerHtml)))
            .ToList();

    foreach (var n in nonEmptyNodes)
    {
        if (IsBr(n) && IsBr(n.NextSibling))
        {
            yield break;
        }

        if (n.Name == "#text")
        {
            yield return n.InnerText.Trim();
        }
    }
}

public bool IsBr(HtmlNode n)
{
    return n != null && n.NodeType == HtmlNodeType.Element && n.Name == "br";
}

哪个返回

在此处输入图像描述

请注意在两个 br 之后它没有返回评论

编辑:

我删除了空#text值,因为当你在最后两个br标签之间有一个换行符时,你实际上得到了一个#text带有换行符的标签。我认为这就是换行混乱所在。

于 2013-10-31T15:39:45.390 回答