Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteUse the following-sibling:: axis for matching siblings after the context node and preceding-sibling:: for matching siblings before it. A sibling is a node with the same parent, so the axis cannot jump into a nested element or another branch of the tree.
Start with an axis and node test, then add predicates for attributes, text, or position: following-sibling::p, preceding-sibling::h2, or following-sibling::div[@class='note']. The examples below show how to select the right parent, avoid the reverse-axis [1] trap, and diagnose empty results.
The sibling rule in XPath
XPath follows the document tree rather than the page’s visual layout. Two nodes are siblings only when they are children of the same parent. The W3C defines the following-sibling axis as the context node’s siblings that occur after it in document order, with preceding-sibling defined in the opposite direction (W3C XPath 2.0 Second Edition). MDN’s XPath axes reference describes the same parent-and-order rule.
An explicit axis step has this form:
axis::node-test[predicate]
axisisfollowing-siblingorpreceding-sibling.node-testis an element name such asp, a wildcard*, or another node test.predicateis optional filtering in square brackets.
Core sibling expressions
| Expression | What it returns | Typical use |
|---|---|---|
following-sibling::p |
Every following sibling paragraph | Read paragraphs that come after a heading or label |
preceding-sibling::h2 |
Every preceding sibling h2 |
Find headings earlier in the same parent |
following-sibling::* |
All following element siblings | Inspect the remaining child elements |
following-sibling::div[@class='note'] |
Following div siblings whose class is exactly note |
Locate a specifically marked note |
../following-sibling::section |
section elements after the context node’s parent |
Move up one level before looking sideways |
Selecting content after a heading
Given this structure:
<article>
<h2>Details</h2>
<p>First detail.</p>
<p>Second detail.</p>
<h2>Examples</h2>
<p>An example.</p>
</article>
To select all paragraph siblings after every matching h2, use:
#1 Best Overall
//h2/following-sibling::p
This expression is literal: each matching heading contributes all later sibling paragraphs, including paragraphs under a later heading because those paragraphs still share the same article parent. If you need paragraphs associated with the nearest preceding heading titled “Details”, test that nearest heading from the paragraph:
//p[preceding-sibling::h2[1][normalize-space(.)='Details']]
This pattern assumes headings and paragraphs are direct children of the same parent and that the nearest preceding h2 defines the section. If the markup nests each section in its own element, select that container instead of relying on sibling order.
Selecting the nearest sibling in either direction
For a forward axis, following-sibling::p[1] means the first matching paragraph after the context node. The positional predicate is evaluated in the axis direction, so it returns the next matching sibling.
preceding-sibling is a reverse axis. Therefore:
preceding-sibling::h2[1]
selects the nearest preceding h2, not the first h2 in document order. Parentheses change the position context:
Recommended Free Tools
Rank #2
- Used Book in Good Condition
(preceding-sibling::h2)[1]
selects the earliest matching preceding h2 in document order. Use the unparenthesized form when you need the closest previous heading; use the parenthesized form when you deliberately need the first one among all preceding matches.
Predicates that make sibling matches precise
Match an attribute
//h2/following-sibling::div[@data-role='summary']
The node must be a following sibling div and its data-role value must equal summary.
Match visible text reliably
//h2/following-sibling::p[normalize-space(.)='Download the report']
normalize-space(.) trims leading and trailing whitespace and collapses internal runs, which is safer than comparing raw text containing formatting whitespace.
Match a class token
An exact @class='note' test fails when an element has multiple classes. For a space-separated class list, use the token pattern:
following-sibling::*[contains(concat(' ', normalize-space(@class), ' '), ' note ')]
Combine position and conditions
following-sibling::li[@data-state='open'][1]
This selects the first following li whose data-state is open; closed items do not consume the position.
When you must move to the parent first
A frequent mistake is asking for a sibling from a child node when the desired sibling belongs to the child’s parent. The abbreviation .. means parent::node().
<div class='card'>
<span class='label'>Status</span>
</div>
<div class='card'>Next card</div>
Starting at span.label, following-sibling::div is empty because the span’s parent is the first div, and that parent has no div sibling inside it. To select the next card, move to the parent, then across:
//span[@class='label']/../following-sibling::div[@class='card']
The same operation written with an explicit parent axis is:
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errors//span[@class='label']/parent::div/following-sibling::div[@class='card']
Nodes for which sibling axes are empty
The sibling axes apply to element, text, comment, and processing-instruction context nodes that participate in a parent’s child list. They are empty for attribute and namespace nodes. If your expression ends at an attribute, first return to its owning element before moving to siblings.
//item/@id/following-sibling::item
does not select anything because an attribute has no siblings on these axes. Instead, select the element and test its attribute:
//item[@id='a']/following-sibling::item
Likewise, a text node inside a paragraph cannot be used to reach a neighboring paragraph with a sibling axis; select the paragraph element as the context.
A repeatable method for writing a sibling XPath
- Inspect the tree. Identify the exact context node and its parent. Developer-tools “Elements” indentation can be misleading when templates insert wrappers, so verify the serialized markup.
- Choose direction. Use
following-siblingfor nodes after the context in document order andpreceding-siblingfor nodes before it. - Choose a node test. Use a tag name for precision,
*for any element, or a predicate when the tag alone is insufficient. - Add predicates. Filter with attributes, normalized text, class-token tests, or a position such as
[1]. - Check position semantics. Remember that
preceding-sibling::X[1]is nearest, while(preceding-sibling::X)[1]is earliest in document order. - Evaluate from the correct level. If the target is a sibling of the context’s parent, insert
..orparent::node(). - Test against real markup. Confirm namespaces, generated wrappers, and actual attribute values in the document supplied to the XPath engine, not just what a browser visually renders.
Common failures and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| No result from an apparently adjacent element | The elements have different parents | Find their common parent; move with .. or start from that parent. |
| Only the closest previous heading is returned | preceding-sibling::h2[1] uses reverse-axis position |
Use parentheses if you need the earliest preceding heading: (preceding-sibling::h2)[1]. |
| Too many paragraphs are returned | The expression selects every later sibling, crossing later sections | Anchor each paragraph to the nearest preceding heading with preceding-sibling::h2[1], or select a section container. |
| A class predicate misses an element with several classes | Exact equality was used | Use the whitespace-delimited token expression with contains(concat(...)). |
| An attribute-based sibling query is empty | The context node is an attribute or namespace node | Move the predicate onto the element, for example //item[@id='a']/following-sibling::item. |
| Nodes outside the intended section appear | following:: was used instead of a sibling axis |
Use following-sibling::; following:: can reach descendants of later branches, not just the current parent’s children. |
| A tag test never matches | Markup uses a namespace or a different element name | Register the namespace with the XPath host and use the qualified name, or inspect the exact serialized tag. |
Sibling axes compared with nearby alternatives
| Axis or step | Scope | Use it when |
|---|---|---|
following-sibling:: |
Later children of the same parent | The target is beside the context node and comes after it. |
preceding-sibling:: |
Earlier children of the same parent | The target is beside the context node and comes before it. |
following:: |
Nodes later in document order beyond the current sibling list | You intentionally need a broader document-order search. |
preceding:: |
Nodes earlier in document order beyond the current sibling list | You intentionally need a broader reverse search. |
child:: or / |
Children of the current node | The target is nested inside the context, not beside it. |
Portability and performance notes
The axis and predicate ideas are defined in the XPath specifications and are available in common XPath implementations. The W3C XPath 2.0 recommendation was published on 14 December 2010 and points readers to the XPath 3 series for later versions; its basic axis definitions remain applicable. Check the version supported by your host before using version-specific functions.
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
Keep the search anchored. An expression such as //h2/following-sibling::p evaluates the sibling step only for matching headings, while an unqualified search beginning at the document root can examine many more nodes. Restricting by tag and attributes improves readability and can reduce work in large documents. When a page has explicit section containers, selecting the container and then its descendants is usually less ambiguous than collecting all later siblings and trying to infer section boundaries.
Or skip the browser setup
If your end goal is a clean visual capture of a page rather than an XPath query, ScreenshotNeo provides a single-request screenshot API. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response reports the page verdict and billing status in X-Page-Verdict and X-Billed headers.
Use the API examples in the ScreenshotNeo documentation. Replace YOUR_API_KEY and the target URL with your values.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots, and every feature is included on every plan. Create a free ScreenshotNeo account.
Frequently Asked Questions
Does whitespace between two elements change whether they are siblings?
Whitespace text nodes may sit between element siblings, but an element node test such as following-sibling::p selects matching element siblings regardless of those intervening text nodes.
How can I select the first sibling that satisfies a condition?
Put the condition before the positional predicate, for example following-sibling::li[@data-state='open'][1]; this makes position apply to the filtered matches.
Where is the formal definition of these axes?
The W3C XPath 2.0 Second Edition defines the sibling axes at w3.org/TR/xpath20/ and points readers toward the later XPath 3 series.
The Bottom Line
Use following-sibling:: or preceding-sibling:: only when the target shares the context node’s parent; then narrow the result with predicates and handle reverse-axis positions deliberately.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




