<div class="mvb"><b>Date 1</b></div>
<div class="mxb"><b>Header 1</b></div>
<div>
inner hmtl 1
</div>
<div class="mvb"><b>Date 2</b></div>
<div class="mxb"><b>Header 2</b></div>
<div>
inner html 2
</div>
我想以这样的方式解析标签之间的内部html
换句话说,在我解析内部html 1时,我想知道包含“Date 1”和“Header 1”的html节点已被解析(但是包含“Date 2”和“Header”的节点2“尚未解析”
如果我通过常规文本解析执行此操作,我会一次读取一行并记录最后一个“日期”和“标题”,而不是我解析过的。然后,当解析内部html 1时,我可以引用最后解析的“Date”和“Header”对象将它们关联在一起。
答案 0 :(得分:1)
使用Html Agility Pack,你可以利用XPATH的力量 - 而忘记那个冗长的xlinq废话:-)。 XPATH position()函数是上下文敏感的。以下是示例代码:
HtmlDocument doc = new HtmlDocument();
doc.Load("your html file");
// select all DIV without a CLASS attribute defined
foreach (HtmlNode div in doc.DocumentNode.SelectNodes("//div[not(@class)]"))
{
Console.WriteLine("div=" + div.InnerText.Trim());
Console.WriteLine(" header=" + div.SelectSingleNode("preceding-sibling::div[position()=1]/b").InnerText);
Console.WriteLine(" date=" + div.SelectSingleNode("preceding-sibling::div[position()=2]/b").InnerText);
}
这将用你的样本打印出来:
div=inner hmtl 1
header=Header 1
date=Date 1
div=inner html 2
header=Header 2
date=Date 2
答案 1 :(得分:0)
嗯,你可以用几种方式做到这一点......
例如,如果要解析的HTML是您在问题中编写的HTML,则可以采用以下方式:
如果一切正常并且HTML具有该布局,则3个集合中的元素数量将相同。
然后你可以很容易地做到:
for (int i = 0; i < innerTexts.Count; i++) {
//Get Date, Headers and Inner Texts at position i
}
以下内容应该有效:
var document = new HtmlWeb().Load("http://www.url.com"); //Or load it from a Stream, local file, etc.
var dateNodes = document.DocumentNode.SelectNodes("//div[@class='mvb']/b");
var headerNodes = document.DocumentNode.SelectNodes("//div[@class='mxb']/b");
var innerTextNodes = (from node in document.DocumentNode.SelectNodes("//div")
let previous = node.PreviousSibling
where previous.Name == "div" && previous.GetAttributeValue("class", "") == "mxb"
select node).ToList();
//Check here if the number of elements of the 3 collections are the same
for (int i = 0; i < dateNodes.Count; i++) {
var date = dateNodes[i].InnerText;
var header = headerNodes[i].InnerText;
var innerText = innerTextNodes[i].InnerText;
//Now you have the set you want: You have the Date, Header and Inner Text
}
这是一种这样做的方式。
当然,您应该检查异常(.SelectNodes(..)
方法没有返回null
),在存储innerTextNodes
时检查LINQ表达式中的错误,并重构for (...)
,也许进入一个接收HtmlNode
的方法并返回它的InnerText
属性。
请记住,在您发布的HTML代码中,您可以知道包含内部文本的<div>
标记的唯一方法是假设它是{{旁边的那个) 1}}包含标题的标记。这就是我使用LINQ表达式的原因。
另一种了解它的方法可能是<div>
具有某些特定属性(如<div>
)或类似属性,或者其中是否包含一些标记而不仅仅是文本。解析HTML时没有魔力:)
修改强>
我还没有测试过这段代码。亲自测试,让我知道它是否有效。