From 657ff90fd1a77c82e0b99ab76518110b81f408d0 Mon Sep 17 00:00:00 2001 From: "Rico Sta. Cruz" Date: Fri, 17 Apr 2015 14:12:29 +0800 Subject: [PATCH] Update the xpath cheatsheet --- assets/style.css | 58 +++++++++- xpath.md | 295 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 323 insertions(+), 30 deletions(-) diff --git a/assets/style.css b/assets/style.css index eed256607..31bad0969 100644 --- a/assets/style.css +++ b/assets/style.css @@ -94,16 +94,68 @@ } } -.greycode code { +pre { + background: #fcfcfc; + border-bottom: solid 1px #eef3fa; +} + +/* + * grey code + */ + +.greycode td:first-child code, +.greycode th:first-child code { background: #f3f3f3; padding: 5px 5px 4px 5px; border-radius: 3px; } -.greycode code + em { - color: #aaa; +.greycode td:first-child code + em, +.greycode th:first-child code + em { + color: #808890; + font-size: 0.9em; + margin: 0 5px; } .greycode a { margin: 0 5px; } + +@media (min-width: 768px) { + table.greycode { + width: calc(620px + 100px); + margin-left: -50px; + background: #fcfcfc; + border-radius: 4px; + border-top: 0; + border-bottom: solid 1px #eef3fa; + } + + table.greycode thead:first-child > tr:first-child > th, + table.greycode thead:first-child > tr:first-child > td, + table.greycode tbody:first-child > tr:first-child > th, + table.greycode tbody:first-child > tr:first-child > td { + border-top: 0; + } + + table.greycode thead > tr:first-child > th, + table.greycode thead > tr:first-child > td, + table.greycode tbody > tr:first-child > th, + table.greycode tbody > tr:first-child > td { + border-top: solid 1px #c7d7ee; + } + + table.greycode td:first-child, + table.greycode th:first-child { + padding-left: 50px; + } + + table.greycode td:last-child, + table.greycode th:last-child { + padding-right: 50px; + } +} + +.hljs-comment { + font-style: normal; +} diff --git a/xpath.md b/xpath.md index b1f065969..0a0b9aa39 100644 --- a/xpath.md +++ b/xpath.md @@ -3,47 +3,288 @@ title: Xpath layout: default --- +CSS equivalents +--------------- + +| CSS | Xpath | +| --- | --- | +| `div p` | `//div//p` | +| `ul > li` | `//ul/li` | +| `div > *` | `//div/*` | +| `h1 ~ ul` | `//h1/following-sibling::ul` | +| `h1 ~ #id` | `//h1/following-sibling::[@id="id"]` | +| --- | --- | +| `:root` | `/` | +| `:root > body` | `/body` | +| --- | --- | +| `input[type="submit"]` | `//input[@type="submit"]` | +| `a[href^='/']` | `//a[starts-with(@href, '/')]` | +| `a[href$='pdf']` | `//a[ends-with(@href, '.pdf')]` | +| --- | --- | +| `#id` | `//[@id="id"]` | +| `.class` | `//[@class="class"]` *...see below* | +| --- | --- | +| `ul > li:first-child` | `//ul/li[1]` | +| `ul > li:nth-child(2)` | `//ul/li[2]` | +| `ul > li:last-child` | `//ul/li[last()]` | +| --- | --- | +| `li#id:first-child` | `//li[@id="id"][1]` | +| --- | --- | +| `a:first-child` | `//a[1]` | +| `a:last-child` | `//a[last()]` | +| `li:first-of-type` | `//li[not(preceding-sibling::li)]` | +{:.greycode.no-head} + +### Class check +Xpath doesn't have the "check if part of space-separated list" operator, so this is the workaround: + +```sh +//div[contains(concat(' ',normalize-space(@class),' '),' foobar ')] +``` + +### jQuery equivalents +For things that CSS alone can't do. + +| jQuery | Xpath | +| ------ | --- | +| `$('ul > li').parent()` | `//ul/li/..` | +| `$('li').closest('section')` | `//li/ancestor-or-self::section` | +| `$('a').attr('href')` | `//a/@href` | +| `$('span').text()` | `//span/text()` | +{:.greycode.no-head} + + +Expressions +----------- + ### Prefixes +Begin your expression with any of these. - // anywhere # //hr[@class='edge'] - ./ relative # ./a - / root # /html/body/div +| Prefix | Example | +| --- | --- | +| `//` *anywhere* | `//hr[@class='edge']` | +| `./` *relative* | `./a` | +| `/` *root* | `/html/body/div` | +{:.greycode.no-head} -### Conditions (`[]`) +### Axes +Separate your steps with `/`. Use two (`//`) if you don't want direct descendants. - # div[@class="head"] - # div[@class="head" and @id="top"] +| Axis | Example | +| --- | --- | +| `/` *child* | `//ul/li/a` | +| `//` *descendant* | `//[@id="list"]//a` | +{:.greycode.no-head} + +### Selecting node data + +```sh +//a #=> +//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. + +```sh +//div[true()] +//div[@class="head"] +//div[@class="head"][@id="top"] +``` + +### Operators +Use 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 +You can use nodes inside predicates. + +```sh +# Use them inside functions + //ul[count(li) > 2] + //ul[count(li[@class='hide']) > 0] +``` + +```sh +# This returns `