Also available in: Español · Português · Français · العربية
XPath Tester
Evaluate an XPath expression against your XML and see which of its functions browsers actually support — and what to write instead.
What is an XPath tester?
XPath is the language for pointing at parts of an XML document: a path like //a[@class='external'] selects every link with that class, wherever it sits in the tree. It is what scraping libraries, XSLT stylesheets, browser automation tools and a great many configuration formats use when they need to say which element they mean.
An XPath tester lets you write an expression, run it against a document you supply, and see what comes back before you commit it to code. That matters because XPath fails quietly in both directions — an expression that selects nothing looks much like an expression that is wrong, and an expression that errors gives you a message about syntax when the real problem is that the function you used does not exist.
This one runs the expression in your own browser's XPath engine, which is the same engine your page scripts would use. It also reads the expression and tells you which functions and axes are actually available there, which is the part most testers leave you to find out the hard way.
How to use it
- Write your expression. Anything from a simple path to a predicate-heavy one. The analysis underneath updates as you type, before you have even run it.
- Paste the XML to search. A fragment of the real document is best. It is parsed as XML, so it needs to be well-formed — an unclosed tag is reported as a parse error rather than silently ignored.
- Read both panels. The results are what your browser's engine returned. Underneath, every function and axis in your expression is listed as available or not, with the XPath 1.0 replacement where one exists.
Browsers only speak XPath 1.0
The XPath built into every browser is the 1999 version, and nothing since. That specification defines a core function library of exactly twenty-seven functions and exactly thirteen axes — that is the whole language as far as a browser is concerned. XPath 2.0 and 3.1 added a great deal, and none of it is available to you here; those live in XSLT 2.0 processors and in language bindings that ship their own engine.
The gap is not the tidy one you would expect. starts-with() is in the twenty-seven. contains() is in the twenty-seven. ends-with() is not — it arrived in XPath 2.0 — which means the single most natural way to select links to PDF files is precisely the form that cannot run, and the error your browser raises talks about the expression rather than about the version. That asymmetry catches people out constantly, and it is the reason this page exists rather than being another box that runs a query.
The same applies across the board. There is no regular-expression support at all: matches(), replace() and tokenize() are all later additions, and you cannot build them out of what remains. There is no lower-case() or upper-case(). There is no min(), max(), avg() or abs(). Those are not obscure corners — they are the functions people reach for first.
Some of these have honest XPath 1.0 replacements and some genuinely do not, and knowing which is which saves an afternoon. ends-with() rewrites exactly, using substring() and string-length() and remembering that XPath counts characters from one rather than zero. Case folding can be approximated with translate() if you spell out both alphabets, which works for ASCII and nothing else. Regular expressions have no equivalent whatsoever and have to move out of the query and into the code around it.
Honest limitations
Your document is parsed as XML, not as HTML. That is the stricter of the two, and it is deliberate: XPath is defined over an XML tree, and parsing loosely would let you write expressions here that behave differently against a real document. The practical consequence is that a fragment of real-world HTML with an unclosed tag will be rejected, and you will need to tidy it first.
Namespaces are the sharpest edge in XPath and this page does not smooth it over. If your document declares a default namespace, a plain //title will select nothing at all, because in XPath 1.0 an unprefixed name means no namespace rather than the default one. There is no way around this in the language itself — you need either a namespace resolver, which is a function and therefore cannot be typed into a text box, or the local-name() workaround.
The check this page makes on your expression reads it rather than executing it, so it identifies functions and axes by name. An expression can pass that check and still be wrong for reasons no analysis catches — an argument of the wrong type, or a predicate that means something other than you intended. The results panel is the answer; the analysis is there to explain a failure the browser describes badly.
One thing is deliberately reported rather than assumed: the namespace axis is part of XPath 1.0 and has nonetheless been the piece browsers differ on. Rather than tell you what your browser does, the page runs the check in your browser and reports what it finds, which is why that line may differ from what a colleague sees.
Why is it free?
The engine is the one already in your browser, so there is nothing to run and nothing to pay for. Evaluating an XPath expression costs no more than any other bit of page script.
Nothing you paste is uploaded, stored or logged. The XML you are debugging is usually a fragment of somebody's real data, and the reliable way to keep that private is never to receive it.