Axes deep dive
XPath Axes: Navigate Up, Down, and Across the DOM
Axes are the superpower that separates XPath from CSS selectors. Learn the 13 axes with practical Selenium and scraping examples, plus tips to avoid over-matching.
Axes reference table
| Axis | Example | When to use |
|---|---|---|
| child | //div/child::p | Direct children only. |
| parent | //button/parent::* | Move to the parent container. |
| self | //div/self::div | Current node (rarely used directly). |
| ancestor | //input/ancestor::form | Walk upward to the closest form. |
| ancestor-or-self | //li/ancestor-or-self::ul | Return ul ancestors and the li if it is a ul. |
| descendant | //ul/descendant::li | All nested list items. |
| descendant-or-self | //section/descendant-or-self::h2 | Include the current node when it matches. |
| following | //h2/following::p[1] | First paragraph after an h2 (any depth). |
| following-sibling | //label/following-sibling::input | Next sibling inputs after a label. |
| preceding | //h2/preceding::p[1] | Nearest paragraph before an h2. |
| preceding-sibling | //input/preceding-sibling::label | Labels immediately before inputs. |
| attribute | //a/@href | Select attributes as nodes. |
| namespace | //svg/namespace::* | Namespace nodes in XML/SVG. |
Axes patterns for Selenium
//label[text()='Email']/following-sibling::input— connects label to its input.//input[@id='password']/parent::div— find container to assert error state.//tr[td[contains(., 'Active')]]/following-sibling::tr[1]— next row after an active row.//div[contains(@class,'toast')]/preceding::*[1]— element right before a toast.
Axes patterns for scraping
//article/descendant::h2— collect headings in articles.//h2/following::p[1]— first paragraph after each heading.//img/ancestor::figure— caption containers for images.//a/ancestor::div[@class='card']— full card when you have just the link.
Tips
- Start with descendant axes, then switch to ancestor/parent to scope results.
- Use
self::when combining multiple axes in a single expression for clarity. - For performance, avoid
//*where possible—scope to a container ID first. - When debugging, split complex selectors into smaller axis-based parts and test each in the playground.
Practice these axes in the XPath playground or browse ready-made selectors in the examples library.