获取元素后面的 table
Get the table right behind an element
我想获取位于元素后面的 table:
<body>
<h3>test</h3>
<table>
<tr><td>abc</td></tr>
</table>
<h3>test2</h3>
<table>
<tr><td>def</td></tr>
</table>
[...]
</body>
所以我只想获取 h3 元素 "test" 之后的 table (或 table 的内容,但我知道如何做这类事情)。
table "test" 并不总是第一个,也可能在 table.
秒之后的某个地方
[编辑]
你知道为什么这个代码:
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); //your test html
var s = doc.DocumentNode.Descendants("table").Where(_ => _.PreviousSibling.PreviousSibling.Name.Equals("h3") && _.PreviousSibling.PreviousSibling.InnerText.Equals("test"));
foreach (var st in s)
{
Debug.WriteLine(st.InnerHtml);
}
如果我删除“/h3”和 "table" 之后的 return, 不起作用?
看起来像这样:
string html = @"<body><h3>test</h3><table><tr><td>abc</td></tr></table><h3>test2</h3><table><tr><td>def</td></tr></table></body>"
而不是上面的 html 代码,但结果为空...
这听起来像是 XPath 的东西:
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); //your test html
var table = doc.DocumentNode.SelectSingleNode("//h3[text()='test']/following::table");
return table.InnerHtml; //returns: "\r\n <tr><td>abc</td></tr>\r\n "
XPath 来自:XPath - Select first element after some other element
编辑:确切代码的图片:
编辑 2:
您的问题是不一定涉及文本元素。因此,您可以通过检查来解决这个问题:
var table3 = doc.DocumentNode.Descendants().FirstOrDefault(x =>
{
if (x.NodeType == HtmlAgilityPack.HtmlNodeType.Element)
{
if (x.PreviousSibling?.NodeType == HtmlAgilityPack.HtmlNodeType.Text)
{
return x.PreviousSibling.PreviousSibling?.Name == "h3" && x.PreviousSibling.PreviousSibling?.InnerText == "test";
} else
{
return x.PreviousSibling?.Name == "h3" && x.PreviousSibling?.InnerText == "test";
}
}
return false;
});
你可以尝试这样的事情。我发现 Linq 更方便。这只是一个想法,您可以进一步扩展它,或者 post 您的问题在这里,我们可以解决 :)。
抱歉,我没有带 IDE。
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); //your test html
doc.DocumentNode.Descendants("table").Where(_ => _.PreviousSibling.PreviousSibling.Name.Equals("h3"));
顺便说一句,我们需要调用 previousSibling 两次的原因是每个节点之间总是有 1 个 #text 元素。
我想获取位于元素后面的 table:
<body>
<h3>test</h3>
<table>
<tr><td>abc</td></tr>
</table>
<h3>test2</h3>
<table>
<tr><td>def</td></tr>
</table>
[...]
</body>
所以我只想获取 h3 元素 "test" 之后的 table (或 table 的内容,但我知道如何做这类事情)。 table "test" 并不总是第一个,也可能在 table.
秒之后的某个地方[编辑]
你知道为什么这个代码:
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); //your test html
var s = doc.DocumentNode.Descendants("table").Where(_ => _.PreviousSibling.PreviousSibling.Name.Equals("h3") && _.PreviousSibling.PreviousSibling.InnerText.Equals("test"));
foreach (var st in s)
{
Debug.WriteLine(st.InnerHtml);
}
如果我删除“/h3”和 "table" 之后的 return,不起作用?
看起来像这样:
string html = @"<body><h3>test</h3><table><tr><td>abc</td></tr></table><h3>test2</h3><table><tr><td>def</td></tr></table></body>"
而不是上面的 html 代码,但结果为空...
这听起来像是 XPath 的东西:
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); //your test html
var table = doc.DocumentNode.SelectSingleNode("//h3[text()='test']/following::table");
return table.InnerHtml; //returns: "\r\n <tr><td>abc</td></tr>\r\n "
XPath 来自:XPath - Select first element after some other element
编辑:确切代码的图片:
编辑 2: 您的问题是不一定涉及文本元素。因此,您可以通过检查来解决这个问题:
var table3 = doc.DocumentNode.Descendants().FirstOrDefault(x =>
{
if (x.NodeType == HtmlAgilityPack.HtmlNodeType.Element)
{
if (x.PreviousSibling?.NodeType == HtmlAgilityPack.HtmlNodeType.Text)
{
return x.PreviousSibling.PreviousSibling?.Name == "h3" && x.PreviousSibling.PreviousSibling?.InnerText == "test";
} else
{
return x.PreviousSibling?.Name == "h3" && x.PreviousSibling?.InnerText == "test";
}
}
return false;
});
你可以尝试这样的事情。我发现 Linq 更方便。这只是一个想法,您可以进一步扩展它,或者 post 您的问题在这里,我们可以解决 :)。 抱歉,我没有带 IDE。
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); //your test html
doc.DocumentNode.Descendants("table").Where(_ => _.PreviousSibling.PreviousSibling.Name.Equals("h3"));
顺便说一句,我们需要调用 previousSibling 两次的原因是每个节点之间总是有 1 个 #text 元素。