The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →In XPath 1.0, select an element whose name is one of several alternatives with a self:: predicate:
<tag> *[self::book or self::article or self::chapter] </tag>
Written as a complete expression, the portable form is //*[self::book or self::article or self::chapter]. If each alternative is already a complete location path, use the union operator instead: //book | //article | //chapter. XPath 2.0 and later also let you compare a name with a sequence, such as //*[local-name() = ('book', 'article', 'chapter')].
The three patterns at a glance
| Expression | Best for | Version and namespace behavior |
|---|---|---|
//*[self::book or self::article or self::chapter] |
Several element names in one location step | XPath 1.0 compatible; unprefixed names match only no-namespace elements |
//book | //article | //chapter |
Separate, complete paths that should be combined | XPath 1.0 compatible; results are de-duplicated and returned in document order |
//*[name() = ('book', 'article', 'chapter')] |
A sequence of qualified names in XPath 2.0+ | Requires a 2.0-or-newer processor; name comparison is sensitive to the processor’s QName rules |
//*[local-name() = ('book', 'article', 'chapter')] |
Several local names when prefixes vary | XPath 2.0+; ignores namespace identity, so add namespace-uri() when needed |
Use self:: with or in XPath 1.0
A name test such as book checks one element name. A predicate can apply several name tests to the same candidate node. The self:: axis refers to the node currently being tested:
//*[self::book or self::article or self::chapter]
For every element selected by //*, XPath evaluates the predicate. The predicate is true when that element is a book, an article, or a chapter. This syntax works in XPath 1.0 implementations, including many DOM libraries and XML tools that have not adopted XPath 2.0.
#1 Best Overall
Restrict the candidates to a known parent
Starting with a narrower path is usually clearer and faster than scanning the entire document:
/catalog/*[self::book or self::article or self::chapter]
This selects only direct children of catalog. To search descendants below every section, use:
//section//*[self::book or self::article or self::chapter]
The predicate remains the same; only the context path changes.
Example document
<catalog>
<book id="b1"/>
<article id="a1"/>
<video id="v1"/>
<chapter id="c1"/>
</catalog>
Against this document, /catalog/*[self::book or self::article or self::chapter] returns book, article, and chapter, but not video.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use the union operator for separate paths
The vertical bar (|) combines node selections:
//book | //article | //chapter
Each side is an independent location path. The result is one node sequence with duplicates removed and nodes ordered as they occur in the document. This is useful when the alternatives have different paths, not merely different names in one step:
/library/fiction/book | /library/nonfiction/article | /archive/chapter
Do not write //(book|article|chapter) as a shortcut in XPath 1.0. Parenthesized name-test unions are not portable XPath 1.0 syntax. Use separate paths joined by |, or use a self:: predicate.
| versus or
These operators work at different levels:
orcombines boolean conditions inside a predicate. It asks whether the current node satisfies at least one test.|combines node selections. It asks for the nodes returned by the left path and the right path together.
For example, //*[self::book or self::article] tests one candidate at a time. //book | //article evaluates two paths and merges their results.
Rank #2
- Used Book in Good Condition
XPath 2.0 and later: compare against a sequence
If your processor supports XPath 2.0 or newer, a list of names can be represented directly as a sequence:
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →//*[name() = ('book', 'article', 'chapter')]
This is convenient when the list is generated or passed as a parameter. The equivalent local-name form is:
//*[local-name() = ('book', 'article', 'chapter')]
Use name() when the qualified name, including its prefix as represented by the processor, is meaningful. Use local-name() when prefixes may vary and you intentionally want to ignore them. XPath 3.1 additionally supports a wildcard namespace test such as *:book, which matches the local name book regardless of namespace.
When a variable holds the names
In an XPath 2.0+ host, a sequence variable keeps the expression maintainable:
declare variable $names as xs:string* := ('book', 'article', 'chapter');
//*[local-name() = $names]
The exact variable declaration syntax depends on the host language and whether it supports XQuery declarations. In a plain XPath API, pass the sequence through that API’s variable mechanism rather than copying the declaration literally.
Crashes, 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 minuteWindows 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 reinstallNamespaces change what a name means
An unprefixed test such as //book does not automatically match an element in an arbitrary namespace. Consider:
<x:book xmlns:x="urn:example"/>
//book will not select this namespaced element in a namespace-aware XPath engine. Bind the document namespace URI to a prefix in the host application, then use that prefix:
//x:book | //x:article | //x:chapter
The prefix in the XPath does not have to be the same prefix used in the XML document; it must be bound to the same namespace URI by the XPath host.
When the prefix is unknown or dynamic
If you cannot bind a stable prefix, test both the local name and namespace URI:
//*[local-name() = 'book' and namespace-uri() = 'urn:example']
For several names in that namespace:
//*[local-name() = ('book', 'article', 'chapter') and namespace-uri() = 'urn:example']
This prevents an unrelated book element from another namespace from being selected. Do not rely on local-name() alone when namespace identity matters.
Choosing the right expression
Choose self:: when alternatives share one step
Use self:: with or when the candidates are interchangeable children or descendants at one point in the path. It is the safest choice for XPath 1.0 portability and makes the context explicit.
Choose | when paths differ
Use a union when each alternative has its own location path, parent, predicate, or axis. For example:
//feed/item[@type='book'] | //catalog/article[@published='yes']
The union result is still one ordered node sequence, even though the paths are unrelated.
Choose sequence comparison for a maintained list
Use name() = (...) or local-name() = (...) in XPath 2.0+ when names come from a sequence, configuration value, or variable. It avoids a long chain of or clauses, but it is not available in XPath 1.0 engines.
Choose qualified names when namespaces are part of the contract
Use a resolver-bound prefix, such as x:book, when the vocabulary’s namespace is known. This is more precise than stripping namespaces and is the preferred approach for schema-driven XML.
Predicates, attributes, and text after the name test
You can add ordinary predicates after the multi-name test. For example, to select matching elements with an id attribute:
//*[self::book or self::article or self::chapter][@id]
To require non-empty text:
//*[self::book or self::article or self::chapter][normalize-space()]
With a union, put conditions on each path when the rules differ:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitches//book[@status='current'] | //article[@published='yes']
Putting one predicate around the entire union is possible in XPath versions that allow a parenthesized path expression, but separate predicates are often easier to read and more portable across older host APIs.
Troubleshooting common failures
No nodes are returned
- Namespace mismatch: The XML elements are namespaced, but the expression uses unprefixed names. Bind the namespace or add a namespace URI test.
- Wrong context: The expression starts from a different document node or parent than expected. Test a short path such as
/*, then extend it one step at a time. - Case mismatch: XPath name tests are case-sensitive.
Bookandbookare different names. - Unsupported version: A 1.0 engine will reject sequence syntax such as
('book', 'article'). Replace it withself::book or self::articleor a union.
Too many nodes are returned
- Namespace ignored: A local-name test may match the same local name from several vocabularies. Add
namespace-uri()or use a bound prefix. - Descendant search too broad:
//*examines every descendant. Start from the known parent or use a direct-child step such as/catalog/*. - Duplicate-looking results: A union removes the same node if multiple paths reach it, but distinct elements with identical content are still separate nodes.
The expression is rejected as invalid
Check for //(book|article|chapter), which is not the portable XPath 1.0 form. Replace it with //book | //article | //chapter or the self:: predicate. Also verify whether the host expects an XPath expression, an XSLT match pattern, or an XML Schema selector; those languages have different namespace and grammar rules.
Performance and maintainability
For a small, fixed list, the performance difference between a self:: predicate and a union is normally less important than the size of the context selected by the path. Avoid starting with //* when the document structure gives you a narrower parent. Namespace-qualified tests also make the intended vocabulary explicit and reduce accidental matches.
Keep a frequently changing candidate list in one variable or configuration value when XPath 2.0+ is available. In XPath 1.0, generate the predicate or union in application code, but validate the names before inserting them into an expression. Never concatenate untrusted input into XPath without escaping or parameterization supported by your host library.
Best Value
Or skip the browser setup
If you are documenting XPath results in a web page and need a clean image or PDF of that page, ScreenshotNeo can capture it with one request instead of configuring a headless browser. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Every plan includes every feature; the free plan includes 1,000 shots per month without a card, and paid plans start at $5 for 3,000 shots.
Use the ScreenshotNeo API documentation for the complete option list, including full-page capture, CSS-selector element capture, device presets, custom JavaScript and CSS, waits, request blocking, cookies, headers, geolocation, PDF controls, caching, signed links, asynchronous jobs, bulk capture, and usage reporting.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Create an account at ScreenshotNeo’s free sign-up page to get the 1,000-shot monthly allowance with no card.
FAQ
Does XPath preserve document order when selecting several names?
Yes. A union returns its combined nodes in document order, and a normal location step evaluates candidates in the axis order defined by XPath.
Recommended Free Tools
Can I select attributes with the same technique?
The expressions here target element names. Attributes are selected with an attribute axis or shorthand, such as //*[@id]; attribute names and element names occupy different axes.
Should I use name() or local-name()?
Use name() when the qualified name is significant. Use local-name() only when you deliberately want to ignore prefixes, and pair it with namespace-uri() when multiple namespaces are possible.
Is | the same as boolean OR?
No. | merges node selections, while or evaluates boolean conditions inside a predicate.
Frequently Asked Questions
Does XPath preserve document order when selecting several names?
Yes. A union returns its combined nodes in document order, and a normal location step evaluates candidates in the axis order defined by XPath.
Free tools Windows power users keep installed
One-click scans. No signup required.
Can I select attributes with the same technique?
The expressions here target element names. Attributes are selected with an attribute axis or shorthand, such as //*[@id]; attribute names and element names occupy different axes.
Should I use name() or local-name()?
Use name() when the qualified name is significant. Use local-name() only when you deliberately want to ignore prefixes, and pair it with namespace-uri() when multiple namespaces are possible.
Is | the same as boolean OR?
No. | merges node selections, while or evaluates boolean conditions inside a predicate.
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.

