3

Here's one tricky scenario:

#target ~ p {
  background: green;
  color: white;
}
<h1 id="target">Title</h1>
<span>Some description</span>
<p>Yes</p>
<p>Yes</p>

<h1>Another Title</h1>
<span>Some description</span>
<p>No</p>
<p>No</p>

Does xpath allow selecting siblings but stop at a point? I would like to select the two <p>s under the first <h1> but not the ones under the second <h1>. Modifying the HTML is not possible as I am doing some web scraping and I am looking for a quick and dirty way of extracting data from paragraphs under a certain heading:

paragraphs = target.select("~ p")
Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247

2 Answers2

4

Try this:

#target ~ p:not(:nth-last-of-type(-n+2)) {
  background: green;
  color: white;
}
<h1 id="target">Title</h1>
<span>Some description</span>
<p>Yes</p>
<p>Yes</p>

<h1>Another Title</h1>
<span>Some description</span>
<p>No</p>
<p>No</p>

Or

#target + span + p,
#target + span + p + p {
  background: green;
  color: white;
}
<h1 id="target">Title</h1>
<span>Some description</span>
<p>Yes</p>
<p>Yes</p>

<h1>Another Title</h1>
<span>Some description</span>
<p>No</p>
<p>No</p>

Or

#target ~ p:nth-of-type(1),
#target ~ p:nth-of-type(2) {
  background: green;
  color: white;
}
<h1 id="target">Title</h1>
<span>Some description</span>
<p>Yes</p>
<p>Yes</p>

<h1>Another Title</h1>
<span>Some description</span>
<p>No</p>
<p>No</p>
Stickers
  • 75,527
  • 23
  • 147
  • 186
1

You can use below XPath expression to get required paragraphs:

//h1/following-sibling::p[count(preceding-sibling::h1)=1]

If you know text of each h1, then you also can try:

//h1[.="Title"]/following-sibling::p[following-sibling::h1[.="Another Title"]]
Andersson
  • 51,635
  • 17
  • 77
  • 129