From 3d70f16b77ece2301d1e531303bdfa2a3bed186e Mon Sep 17 00:00:00 2001 From: "Rico Sta. Cruz" Date: Wed, 30 Aug 2017 06:50:54 +0800 Subject: [PATCH] xpath: update --- xpath.md | 254 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 146 insertions(+), 108 deletions(-) diff --git a/xpath.md b/xpath.md index a761d4cb9..adc047794 100644 --- a/xpath.md +++ b/xpath.md @@ -1,11 +1,13 @@ --- title: Xpath category: HTML -layout: default-ad +layout: 2017/sheet tags: [Featured] weight: -5 --- +## Selectors + ### Descendant selectors | CSS | Xpath | ? | @@ -18,7 +20,7 @@ weight: -5 | ---- | ---- | -- | | `:root` | `/` | [?](#prefixes) | | `:root > body` | `/body` | | -{:.greycode.no-head.xp} +{: .xp} ### Attribute selectors @@ -33,7 +35,7 @@ weight: -5 | `a[href^='/']` | `//a[starts-with(@href, '/')]` | [?](#string-functions) | | `a[href$='pdf']` | `//a[ends-with(@href, '.pdf')]` | | | `a[href~='://']` | `//a[contains(@href, '://')]` *...[kinda](#class-check)* | | -{:.greycode.no-head.xp} +{: .xp} ### Order selectors @@ -45,7 +47,7 @@ weight: -5 | `li#id:first-child` | `//li[@id="id"][1]` | | | `a:first-child` | `//a[1]` | | | `a:last-child` | `//a[last()]` | | -{:.greycode.no-head.xp} +{: .xp} ### Siblings @@ -54,7 +56,7 @@ weight: -5 | `h1 ~ ul` | `//h1/following-sibling::ul` | [?](#using-axes) | | `h1 + ul` | `//h1/following-sibling::ul[1]` | | | `h1 ~ #id` | `//h1/following-sibling::[@id="id"]` | | -{:.greycode.no-head.xp} +{: .xp} ### jQuery @@ -64,7 +66,7 @@ weight: -5 | `$('li').closest('section')` | `//li/ancestor-or-self::section` | | | `$('a').attr('href')` | `//a/@href` | [?](#steps) | | `$('span').text()` | `//span/text()` | | -{:.greycode.no-head.xp} +{: .xp} ### Other things @@ -78,111 +80,119 @@ weight: -5 | Has children (specific) | `//ul[li]` | | | Or logic | `//a[@name or @href]` | [?](#operators) | | Union (joins results) | `//a | //div` | [?](#unions) | -{:.greycode.no-head.xp} +{: .xp} ### Class check -Xpath doesn't have the "check if part of space-separated list" operator, so this is the workaround ([source](http://pivotallabs.com/xpath-css-class-matching/)): -```sh +```bash //div[contains(concat(' ',normalize-space(@class),' '),' foobar ')] ``` -{:.light} + +Xpath doesn't have the "check if part of space-separated list" operator, so this is the workaround ([source](http://pivotallabs.com/xpath-css-class-matching/)). Expressions ----------- +### Steps and axes + +| `//` | `ul` | `/` | `a[@id='link']` | +| Axis | Step | Axis | Step | +{: .-css-breakdown} + ### Prefixes + +| Prefix | Example | What | +| --- | --- | --- | +| `//` | `//hr[@class='edge']` | Anywhere | +| `./` | `./a` | Relative | +| `/` | `/html/body/div` | Root | +{: .-headers} + Begin your expression with any of these. -| Prefix | Example | -| --- | --- | -| `//` *anywhere* | `//hr[@class='edge']` | -| `./` *relative* | `./a` | -| `/` *root* | `/html/body/div` | -{:.greycode.no-head} - ### Axes + +| Axis | Example | What | +| --- | --- | --- | +| `/` | `//ul/li/a` | Child | +| `//` | `//[@id="list"]//a` | Descendant | +{: .-headers} + Separate your steps with `/`. Use two (`//`) if you don't want to select direct children. -| Axis | Example | -| --- | --- | -| `/` *child* | `//ul/li/a` | -| `//` *descendant* | `//[@id="list"]//a` | -{:.greycode.no-head} - ### Steps -A step may have an element name (`div`) and [predicates](#predicate) (`[...]`). Both are optional. -```sh +```bash //div //div[@name='box'] //[@id='link'] ``` -{:.light} -They can also be these other things. +A step may have an element name (`div`) and [predicates](#predicate) (`[...]`). Both are optional. +They can also be these other things: -```sh -//a/text() #=> "Go home" -//a/@href #=> "index.html" -//a/* #=> All a's child elements +```bash +//a/text() #=> "Go home" +//a/@href #=> "index.html" +//a/* #=> All a's child elements ``` Predicates ---------- -### Predicates (`[...]`) -Restricts a nodeset only if some condition is true. They can be chained. +### Predicates -```sh +```bash //div[true()] //div[@class="head"] //div[@class="head"][@id="top"] ``` -{:.light} + +Restricts a nodeset only if some condition is true. They can be chained. ### Operators + +```bash +# Comparison +//a[@id = "xyz"] +//a[@id != "xyz"] +//a[@price > 25] +``` + +```bash +# Logic (and/or) +//div[@id="head" and position()=2] +//div[(x and y) or not(z)] +``` + Use comparison and logic operators to make conditionals. -```sh -# Comparison - //a[@id = "xyz"] - //a[@id != "xyz"] - //a[@price > 25] -``` - -```sh -# Logic (and/or) - //div[@id="head" and position()=2] - //div[(x and y) or not(z)] -``` - ### Using nodes + +```bash +# Use them inside functions +//ul[count(li) > 2] +//ul[count(li[@class='hide']) > 0] +``` + +```bash +# This returns `