Derek 朕會功夫
Derek 朕會功夫

Reputation: 94339

Select siblings but without something in between

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")

Upvotes: 3

Views: 76

Answers (2)

Stickers
Stickers

Reputation: 78716

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>

Upvotes: 4

Andersson
Andersson

Reputation: 52685

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"]]

Upvotes: 1

Related Questions