Free tools Windows power users keep installed
One-click scans. No signup required.
In XPath 1.0, select elements whose name is one of several alternatives with a wildcard step and self:: tests:
//*[self::book or self::article or self::chapter]
If each alternative is already a complete location path, combine those paths with the union operator:
//book | //article | //chapter
XPath 2.0 and later also let you compare a name with a sequence, while namespace-qualified documents require a bound prefix or an explicit namespace URI test.
The three patterns to know
| Situation | Expression | Best fit |
|---|---|---|
| One location step, XPath 1.0 compatibility | //*[self::book or self::article or self::chapter] |
Several element names at the same point in a path |
| Separate complete paths | //book | //article | //chapter |
Alternatives that may start from different locations |
| XPath 2.0 or newer | //*[local-name() = ('book', 'article', 'chapter')] |
A candidate list naturally represented as a sequence |
| Known namespace | //x:book | //x:article | //x:chapter |
Namespace identity must be enforced |
These expressions are not interchangeable in every context. The first uses a boolean predicate on the current node; | combines node selections; sequence comparison is available only in XPath 2.0 and later.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
XPath 1.0: use self:: with or
XPath 1.0 has no sequence literal such as ('book', 'article'). The portable way to test several element names in one location step is:
//*[self::book or self::article or self::chapter]
The * name test first allows any element. The predicate then evaluates three name tests against the node currently being considered. self::book is true when that node is a book; the other tests work the same way. The boolean or succeeds when at least one test is true.
Restrict the search to a known parent
A leading // searches descendants throughout the document. If the alternatives occur only under a particular element, narrow the path:
/library/*[self::book or self::article or self::chapter]
This selects only direct children of library. To search descendants below that element, use:
/library//*[self::book or self::article or self::chapter]
Narrowing the context makes the intent clearer and can reduce work for an XPath engine.
Use longer predicates when the names are part of a larger condition
The name test can sit beside ordinary predicates:
//*[self::book or self::article][@published = 'yes']
Here the node must be either a book or an article, and it must also have a published attribute whose value is yes. Parentheses around the name alternatives are unnecessary because each self:: test is already a complete boolean operand.
Rank #2
- Used Book in Good Condition
Use the union operator for separate paths
When the candidates are complete, independent location paths, join them with |:
//book | //article | //chapter
XPath defines union and | as equivalent. The result combines the selected node sequences, removes duplicates, and presents the nodes in document order. This is different from boolean or, which only decides whether a predicate is true.
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 minuteWhen union is clearer
Union is useful when each branch has a different path or predicate:
/catalog/section/book[@status = 'current'] | /archive/article[@year > 2020]
The two branches do not need to share the same parent or step. For alternatives within one wildcard step, the self:: form generally communicates the structure more directly.
Do not use the XPath 1.0 shorthand that looks like a grouped name test
This expression is not portable XPath 1.0:
//(book|article|chapter)
Use separate paths joined by |, or use the self:: predicate instead. Parenthesized expressions can be valid in other XPath contexts, but the grouped name-test syntax above should not be relied on for XPath 1.0 processors.
XPath 2.0 and later: compare with a sequence
If the processor supports XPath 2.0 or newer, represent the candidate names as a sequence:
Recommended Free Tools
//*[local-name() = ('book', 'article', 'chapter')]
The comparison is true when the current element’s local name equals any item in the sequence. This is convenient when the list is generated or maintained as data rather than repeated as several boolean operands.
name() versus local-name()
name() returns the node’s name as presented by the processor and can include a namespace prefix. local-name() returns only the local part. In a namespace-aware document, stripping the namespace can make unrelated elements with the same local name match, so do not use local-name() alone when namespace identity matters.
XPath 3.1 wildcard local-name tests
XPath 3.1 defines wildcard tests such as:
*:book
This matches an element whose local name is book regardless of its namespace. It is concise, but it deliberately ignores which namespace supplied the name. Use it only when that behavior is wanted.
Namespaces: the difference between a name and a local name
An unprefixed element name does not automatically match an element in an arbitrary namespace. For XML such as:
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 →<x:book xmlns:x='urn:example' />
the XPath host must bind a prefix to the namespace URI, then use that prefix in the expression:
//x:book | //x:article | //x:chapter
The prefix in the XPath expression is a host-side binding; it does not have to be the same spelling as the prefix used in the source XML. What matters is that both resolve to the same namespace URI. Oracle’s XPath tutorial describes this name-test mechanism, and namespace-aware APIs require the host’s namespace resolver to be configured before evaluation.
When the prefix is unknown or dynamic
If you cannot rely on a stable prefix, test both the local name and the namespace URI:
//*[local-name() = 'book' and namespace-uri() = 'urn:example']
For several names in XPath 2.0 or later:
//*[local-name() = ('book', 'article', 'chapter') and namespace-uri() = 'urn:example']
This prevents an element named book in a different namespace from being selected accidentally. MDN documents local-name() together with namespace-uri() for this namespace-robust pattern.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesChoosing between or, |, and sequence comparison
| Question | Choose | Reason |
|---|---|---|
| Must it run on an XPath 1.0 engine? | self::name or self::name2 |
Works in a single location step without XPath 2.0 features. |
| Do you already have independent full paths? | path1 | path2 |
Unites node selections, removes duplicates, and returns document order. |
| Is the processor XPath 2.0+ and the list is naturally data? | local-name() = ('a', 'b') |
Expresses membership in a sequence directly. |
| Does namespace identity matter? | Bound QName such as x:book |
Matches the intended expanded name instead of every same-named element. |
| Is the namespace prefix unpredictable? | local-name() plus namespace-uri() |
Checks the URI explicitly while tolerating prefix changes. |
Do not confuse the operators: or combines boolean conditions inside a predicate; | combines node selections. Replacing one with the other changes the expression’s type and meaning.
A practical way to build and verify the expression
- Identify the XPath version. Browser DOM XPath evaluators and many older XML APIs expose XPath 1.0, so start with the
self::form unless the host explicitly supports XPath 2.0 or newer. - Write one working name test. Try
//bookor a namespace-qualified equivalent before adding alternatives. If one name does not match, adding more names will not fix a namespace or context error. - Choose the structure. Use a
self::predicate for alternatives within one step; use|when the branches are complete paths. - Check namespaces. Inspect the document’s namespace URI and configure the XPath host’s prefix resolver. If the prefix is dynamic, add
namespace-uri()to the predicate. - Verify the result set. Test a document containing one instance of each candidate, a document containing none, and a document containing repeated candidates. Confirm that the selected nodes are the intended elements and that a union does not introduce duplicate results.
- Compile once when evaluating repeatedly. If the host API supports compiled XPath expressions, reuse the compiled expression and change only the input document or context. Keep the expression itself constant when possible.
Common failures and fixes
No nodes are returned
- The context is wrong:
/library/*[...]requires alibraryroot, while//*searches descendants anywhere. - The XML is namespaced: replace unprefixed tests with a resolver-bound prefix or add
namespace-uri(). - The XPath engine is evaluating a different document than the one you inspected. Log or inspect the actual input and context node.
Elements from the wrong vocabulary are returned
local-name() ignores namespaces. Add an explicit namespace URI test or use a bound prefix. XPath 3.1’s *:book has the same intentional namespace-wildcard behavior.
A syntax error appears near parentheses
Replace //(book|article|chapter) with //*[self::book or self::article or self::chapter] or with //book | //article | //chapter.
The result order is unexpected
A union is a node-set operation, not a concatenation of branch outputs. Its result is normalized to document order, with duplicates removed. If your application needs a custom order, apply an explicit sort after XPath evaluation in the host language.
Best Value
The expression is slow on a large document
- Replace a broad
//*search with the narrowest known parent path. - Use namespace-qualified name tests when the namespace is known instead of examining every element with
local-name(). - Reuse a compiled expression when the host supports compilation.
- Split genuinely unrelated searches only when your host can process them more efficiently; otherwise a single union or predicate is easier to audit.
Examples side by side
Given a document containing book, article, and chapter elements, all of these are valid choices when their version and namespace assumptions are satisfied:
| Goal | Expression |
|---|---|
| XPath 1.0, any descendant element with one of three names | //*[self::book or self::article or self::chapter] |
| Three independent descendant paths | //book | //article | //chapter |
| XPath 2.0+, sequence membership | //*[local-name() = ('book', 'article', 'chapter')] |
| Namespace-qualified alternatives | //x:book | //x:article | //x:chapter |
| Dynamic prefix, fixed namespace URI | //*[local-name() = 'book' and namespace-uri() = 'urn:example'] |
Or skip the browser setup
If your practical goal is to capture a rendered page after locating or checking elements, ScreenshotNeo provides a one-request website screenshot API. It is separate from XPath evaluation: use XPath in your XML or DOM tool when you need node selection, and use the API when you need a clean visual capture of a URL.
Before the capture, ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the page verdict and billing status with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
The API supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, device presets or custom viewports, retina scale, PDF paper and page settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, configurable cache TTLs, signed links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification. Parameters used by other screenshot APIs also work, which can simplify a migration.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →See the ScreenshotNeo documentation for request options. The following calls use the same endpoint and return the image bytes:
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Python
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)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free, and every feature is included on every plan. Create a free ScreenshotNeo account to get the API key.
Frequently Asked Questions
Is name() interchangeable with local-name() when prefixes change?
No. name() can include the prefix selected by the processor, while local-name() removes the prefix. If you need a prefix-independent match, use local-name() together with namespace-uri() whenever multiple namespaces may contain the same local name.
Can a candidate list be supplied at runtime?
In XPath 1.0, construct a predicate with one self:: test per allowed name, or construct separate paths joined with |. In XPath 2.0 and later, represent the runtime list as a sequence and compare the name to that sequence.
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.




