Build complicated XPath queries without the hassle - JavaScript & Python
A chainable API to build complex XPath queries along the different XPath axes. Available both in Python and JavaScript.
- Documentation — Consult the quick start guide and the online documentation.
Installation
xpath-helper
can be installed using npm:
npm install xpath-helper
It can be also be imported as a JavaScript module.
<script type="module" >
import { xh, filter} from 'https://unpkg.com/xpath-helper@latest/dist/mjs/xpath-helper.js';
console.log(
xh.getElementByTag('body').getElementByTag('h1', filter.valueEquals('hello')).toString()
);
</script>
Quick-start
You can chain method call on the different XPath axes and easily add filters.
import { xh, filter } from 'xpath-helper';
const p = xh.getElementByTag('p', filter.attributeContains('class', 'very-nice-p'));
p.toString();
const nextP = p.getFollowingSiblingByTag('p');
nextP.toString();
const modal = xh
.getElement(filter.valueEquals('Register'))
.getAncestor(filter.attributeEquals('class', 'modal'));
modal.toString();
const li = xh.getElementByTag("li",
filter.and(
filter.or(
filter.valueContains("JavaScript"), filter.valueContains("Python")
),
filter.hasAttribute("data-description")
));
li.toString()
Chaining
XPath natively lets your build complex queries chaining them along its different axes. Read this article to understand the different XPath axes.
This library let you do exactly the same by chaining method calls along the different axes: descendant
aliased as element
, descendant-or-self
, child
, parent
, ancestor
, ancestor-or-self
, preceding
, preceding-sibling
, following
, following-sibling
.
For each axis, xpath-helper provides 3 methods, like for instance getElement(filter)
, getElementByTag(tag, filter)
, getElementBySVGTag(svgTag, filter)
for the descendant
axis aliased as element
.
The complete filter API can be found here.
import { xh, filter } from 'xpath-helper';
const el = xh.getElementByTag('p', filter.attributeContains('class', 'very-nice-p'))
.getParent()
.getFollowingSiblingByTag('p');
el.toString();
el = xh.getElementByTag('p', filter.attributeContains('class', 'very-nice-p'))
.getAncestorByTag('div')
.getPrecedingSibling(filter.hasAttribute('data-foo-bar'));
el.toString();
It is also possible to keep a relative path in a variable and re-use it after.
import { xh, filter } from 'xpath-helper';
const modal = xh.getElement(filter.attributeContains('class', 'modal'));
const submitButton = modal.getElementByTag('button', filter.valueEquals('Submit'));
const cancelButton = modal.getElementByTag('button', filter.valueEquals('Cancel'));
Filters
To select elements more precisely you can add filters: on attributes, on element values, element position, and combine them with conditional operators: and(...)
, or(...)
, and not(...)
.
The complete filter API can be found here.
Attributes
Find below a few examples of filters on attributes.
import { xh, filter } from 'xpath-helper';
const el = xh.getElement(filter.attributeEquals('class', 'foo'));
const el2 = xh.getElement(filter.attributeContains('class', 'bar'));
const img = xh.getElementByTag('img', filter.hasAttribute('alt'));
const li = xh.getElementByTag('li', filter.attributeGreaterThan('data-index', 3);)
Values
Find below a few examples of filters on node values.
import { xh, filter } from 'xpath-helper';
const button = xh.getElementByTag('button', filter.valueEquals('Submit'));
const el = xh.getElement(filter.valueContains('foobar'));
const li = xh.getElementByTag('li', filter.valueGreaterThan(3));
Position
Find below a few examples of filters on node position.
import { xh, filter } from 'xpath-helper';
const first = xh.getElementByTag('ul').getElementByTag('li', filter.getFirst());
const last = xh.getElementByTag('ul').getElementByTag('li', filter.getLast());
const third = xh.getElementByTag('ul').getElementByTag('li', filter.get(3));
Conditional expression
Find below a few examples of filters with conditional expression.
import { xh, filter } from 'xpath-helper';
let el = xh.getElement(
filter.attributeContains('class', 'a-link').and(
filter.hasAttribute('href')
)
);
el.toString();
el = xh.getElement(
filter.attributeContains('class', 'foo').or(
filter.attributeContains('class', 'bar')
)
);
el.toString();
el = xh.getElement(
filter.and(
filter.or(
filter.valueContains("JavaScript"),
filter.valueContains("Pyhton")
),
filter.valueContains("package")
)
);
el.toString();
SVG
Navigating into SVG elements from an HTML file can be tricky with XPath, that is why a subset of functions have been added. They are all ending with ...bySVGTag
and can be used as below.
import { xh, filter } from 'xpath-helper';
const path = xh.getElementBySVGTag('path',
filter.attributeEquals('d', 'M 310 130 L 90 130 L 90 183.63')
);
path.toString();
const g = xh.getElementBySVGTag('path', filter.attributeEquals('id', 'id-path'))
.getAncestorBySVGTag('g');
g.toString();