October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
Developer Tools

How to Select an Element with One of Many Names in XPath

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
/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
XPath 2.0 Programmer's Reference
  • 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When 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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
//*[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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choosing 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

  1. 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.
  2. Write one working name test. Try //book or a namespace-qualified equivalent before adding alternatives. If one name does not match, adding more names will not fix a namespace or context error.
  3. Choose the structure. Use a self:: predicate for alternatives within one step; use | when the branches are complete paths.
  4. 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.
  5. 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.
  6. 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.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common failures and fixes

No nodes are returned

  • The context is wrong: /library/*[...] requires a library root, 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.