XPath tester

Run XPath 3.1 against a document and see every match with its line, its path and its value. The prefixes the document declares are bound for you, and unprefixed names match the root element's namespace. Everything runs in your browser.

XML

Names complete as you type; Ctrl + Space lists them XPath cheat sheet XPath 3.1 functions (W3C)

Paste XML above or open a file: expressions to try, written with its element names, appear here. Or load the example, a UBL invoice.

Prefixes

·

No results. Check the prefixes above: unprefixed names match the root element's namespace.

How to test an XPath expression

  1. Paste the XML or open a file. The example is a UBL invoice.
  2. Type an expression and press Evaluate (or Enter), or click one of the expressions suggested under the field: they are written with the document's own element and attribute names.
  3. Each node found is listed with its path and line; click one to jump to it in the editor. Numbers, strings and booleans are shown as values.

Namespaces without the boilerplate

Most XPath testers fail on a document with a default namespace: //Invoice finds nothing, because the element is really {urn:oasis:names:specification:ubl:schema:xsd:Invoice-2}Invoice. Here, unprefixed names in your expression match the root element's namespace, and every prefix the document declares (cbc, cac, ram…) can be used as it is. The bindings in use are listed above the results.

XPath 3.1, not just 1.0

Expressions are evaluated by SaxonJS, which implements XPath 3.1: for and let expressions, if/then/else, regular expressions (matches(), replace()), dates and durations, string-join(), maps and arrays. XPath 1.0 expressions work as they are.

It is the same engine that runs the Schematron business rules in the validator, so an expression that works here works in an <assert test="…">. See the Schematron validator.

XPath cheat sheet

Every expression below runs against the example invoice (Load example above). Once your own document is in, the Cheat sheet for this document tab shows the same kinds of expression written with its element and attribute names, and the field completes names, functions and axes as you type.

Paths

/
The document node, above the root element.
/Invoice
The root element.
/Invoice/*
The elements directly under the root.
/Invoice/cac:InvoiceLine
Invoice lines, by their full path.
//cbc:ID
Every cbc:ID, wherever it is.
//cac:InvoiceLine/cbc:ID
The IDs that are children of an invoice line.
//*
Every element in the document.
//cbc:IssueDate | //cbc:DueDate
Both dates: | joins two selections.
(//cbc:ID)[1]/..
The parent of the first ID; . is the current node.

Position

(//cac:InvoiceLine)[1]
The first invoice line in the document.
//cac:Party/cac:PartyName[1]
The first cac:PartyName of each party: without parentheses, the position counts among siblings.
(//cac:InvoiceLine)[last()]
The last invoice line.
(//cbc:ID)[position() <= 2]
The first two IDs.

Conditions

//cbc:InvoicedQuantity[@unitCode]
Quantities that have a unitCode attribute.
//cbc:InvoicedQuantity[@unitCode = "HUR"]
Quantities in hours.
//cac:InvoiceLine[cbc:LineExtensionAmount > 600]
Lines over 600: a comparison with a number compares numbers.
//cac:InvoiceLine[not(cbc:Note)]
Lines without a note.
//cbc:Name[contains(., "Ltd")]
Names that contain "Ltd".
//cbc:Name[starts-with(., "North")]
Names that start with "North".
//cbc:ID[matches(., "^INV-\d{4}")]
IDs matching a regular expression.
//cac:InvoiceLine[cbc:ID = "1" and cbc:InvoicedQuantity > 5]
Two conditions; or works the same way.

Values and functions

//cbc:IssueDate/text()
The text of an element.
//@currencyID
Every currencyID attribute.
string((//cbc:InvoicedQuantity)[1]/@unitCode)
The first quantity's unit, as a string.
count(//cac:InvoiceLine)
How many lines there are.
sum(//cac:InvoiceLine/cbc:LineExtensionAmount)
The total of the lines; avg(), min() and max() work alike.
distinct-values(//@currencyID)
Each currency once.
string-join(//cac:PartyName/cbc:Name, ", ")
Values joined into one string.
name(/*) and local-name(/*)
The root's name with and without its prefix; namespace-uri(/*) gives its namespace.
lower-case(//cbc:DocumentCurrencyCode)
Also upper-case(), normalize-space(), substring(), replace(), tokenize().
round(avg(//cac:InvoiceLine/cbc:LineExtensionAmount), 2)
A number rounded to two decimals.

Axes

//cbc:DueDate/preceding-sibling::*
The elements before cbc:DueDate under the same parent; following-sibling:: gives those after it.
//cbc:Name/ancestor::cac:Party
The party a name belongs to.
(//cac:InvoiceLine)[1]/descendant::*
Everything inside the first line.

XPath 3.1

//cac:InvoiceLine ! (cbc:LineExtensionAmount * 2)
The simple map operator: a value per line.
for $line in //cac:InvoiceLine return $line/cbc:ID || ": " || $line/cbc:LineExtensionAmount
A loop, and || to join strings.
let $total := sum(//cac:InvoiceLine/cbc:LineExtensionAmount) return $total = //cbc:LineExtensionAmount[parent::cac:LegalMonetaryTotal]
A variable: do the lines add up to the total?
if (count(//cac:InvoiceLine) > 1) then "several lines" else "one line"
A condition.
days-from-duration(xs:date(//cbc:DueDate) - xs:date(//cbc:IssueDate))
Days between two dates.
//cac:InvoiceLine => count()
The arrow operator: the value on the left is the first argument.

The full lists are in the W3C recommendations: XML Path Language (XPath) 3.1 for the syntax, axes and operators, and XPath and XQuery Functions and Operators 3.1 for every function.

Questions

Is my XML uploaded?

No. The document is parsed and the expression evaluated in your browser, in a background worker.

Which XPath version is supported?

XPath 3.1, through SaxonJS. XPath 1.0 and 2.0 expressions work too.

Why does my expression find nothing?

Usually a namespace. Unprefixed names here match the root element's namespace; an element in another namespace needs the prefix the document uses for it.

How many results are shown?

The first 500, with the total count.

Other tools

  • XML formatter: Pretty-print or minify XML, keeping text, CDATA and comments as written.
  • XSD generator: Infer an XML Schema from sample documents, checked against them.
  • XML from XSD: Generate a sample XML document from a schema, validated against it.
  • XSLT transformer: Run XSLT 1.0, 2.0 or 3.0 on a document and see the result, the messages and the files it writes.
  • XML diff: Compare two XML documents as trees: changed, added and removed elements, attributes and text.
  • XML to JSON converter: Convert XML to JSON, with arrays where an element repeats or wherever its XSD allows.
  • JSON to XML converter: Convert JSON to XML: @keys become attributes, arrays repeated elements.
  • XML to CSV converter: Turn a repeating element into CSV rows: invoice lines, products, records.
  • E-invoice viewer: Read an XRechnung, ZUGFeRD, Factur-X or Peppol invoice as a document, and print it.
  • XML validator: check a document against XSD, DTD, RelaxNG or Schematron, up to 1 GB.