XML XPath
Querying and selecting XML nodes with precision
🎯 What is XPath?
XPath (XML Path Language) is a query language for selecting nodes from XML documents. It uses path expressions to navigate through elements and attributes, making it easy to locate specific data within complex XML structures.
// XPath query example
const result = xmlDoc.evaluate("//book/title", xmlDoc, null,
XPathResult.ANY_TYPE, null);
Purpose:
XPath provides powerful syntax to select specific nodes from XML documents.
Key XPath Concepts
Paths
Navigate XML structure
/library/book/title
Predicates
Filter nodes with conditions
//book[@price < 30]
Axes
Define node relationships
child::book
parent::library
Functions
Built-in XPath functions
count(//book)
text()
🔹 Basic XPath Syntax
XPath uses path expressions similar to file system paths. Understanding basic syntax is essential for querying XML documents effectively.
Common XPath Expressions:
- / - Selects from root node
- // - Selects nodes anywhere in document
- . - Selects current node
- .. - Selects parent of current node
- @ - Selects attributes
- * - Matches any element
<!-- Sample XML -->
<library>
<book id="B001">
<title>XML Basics</title>
<author>John Doe</author>
<price>29.99</price>
</book>
<book id="B002">
<title>Advanced XML</title>
<author>Jane Smith</author>
<price>39.99</price>
</book>
</library>
// XPath Examples
"/library/book" // All book elements under library
"//title" // All title elements anywhere
"//book[@id='B001']" // Book with id="B001"
"//book/title" // All titles in books
"//book[1]" // First book element
"//book/price/text()" // Text content of price elements
"//@id" // All id attributes
🔹 Using XPath in JavaScript
JavaScript provides the evaluate() method to execute XPath queries on XML documents. Here's how to use it effectively.
<!DOCTYPE html>
<html>
<body>
<h2>XPath Query Example</h2>
<div id="output"></div>
<script>
const xmlString = `
<bookstore>
<book category="fiction">
<title>Harry Potter</title>
<author>J.K. Rowling</author>
<price>29.99</price>
</book>
<book category="science">
<title>A Brief History</title>
<author>Stephen Hawking</author>
<price>19.99</price>
</book>
<book category="fiction">
<title>The Hobbit</title>
<author>J.R.R. Tolkien</author>
<price>24.99</price>
</book>
</bookstore>`;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
// XPath query: Get all fiction books
const xpath = "//book[@category='fiction']/title";
const result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
let output = "<h3>Fiction Books:</h3>";
for (let i = 0; i < result.snapshotLength; i++) {
const node = result.snapshotItem(i);
output += "<p>" + node.textContent + "</p>";
}
document.getElementById("output").innerHTML = output;
</script>
</body>
</html>
Output:
Fiction Books:
Harry Potter
The Hobbit
🔹 XPath Predicates
Predicates filter nodes based on conditions. They're enclosed in square brackets and allow you to select specific nodes that meet certain criteria.
const xmlString = `
<products>
<product id="1">
<name>Laptop</name>
<price>999</price>
</product>
<product id="2">
<name>Mouse</name>
<price>25</price>
</product>
<product id="3">
<name>Keyboard</name>
<price>75</price>
</product>
</products>`;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
// Products with price less than 100
let xpath = "//product[price < 100]/name";
let result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
console.log("Products under $100:");
for (let i = 0; i < result.snapshotLength; i++) {
console.log("- " + result.snapshotItem(i).textContent);
}
// First product
xpath = "//product[1]/name";
result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
console.log("\nFirst product: " + result.singleNodeValue.textContent);
// Last product
xpath = "//product[last()]/name";
result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
console.log("Last product: " + result.singleNodeValue.textContent);
// Product with specific id
xpath = "//product[@id='2']/name";
result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
console.log("Product with id=2: " + result.singleNodeValue.textContent);
Console Output:
Products under $100:
- Mouse
- Keyboard
First product: Laptop
Last product: Keyboard
Product with id=2: Mouse
🔹 XPath Axes
Axes define the relationship between nodes in the XML tree. They allow you to navigate in different directions from the current node.
Common Axes:
- child:: Direct children of current node
- parent:: Parent of current node
- descendant:: All descendants (children, grandchildren, etc.)
- ancestor:: All ancestors (parent, grandparent, etc.)
- following-sibling:: Siblings after current node
- preceding-sibling:: Siblings before current node
- attribute:: Attributes of current node
// Axes examples
"child::book" // Same as "book"
"descendant::title" // Same as "//title"
"attribute::id" // Same as "@id"
"//book/child::title" // Direct title children of book
"//title/parent::book" // Parent book of title
"//book[1]/following-sibling::book" // Books after first book
🔹 XPath Functions
XPath provides built-in functions for string manipulation, numeric operations, and node set operations. These functions enhance query capabilities.
const xmlString = `
<library>
<book><title>XML Guide</title></book>
<book><title>JavaScript Basics</title></book>
<book><title>Web Development</title></book>
</library>`;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
// count() - Count number of nodes
let xpath = "count(//book)";
let result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.NUMBER_TYPE, null);
console.log("Total books: " + result.numberValue);
// contains() - Check if string contains substring
xpath = "//book[contains(title, 'XML')]/title";
result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
console.log("Book with 'XML': " + result.singleNodeValue.textContent);
// starts-with() - Check if string starts with substring
xpath = "//book[starts-with(title, 'Web')]/title";
result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
console.log("Book starting with 'Web': " + result.singleNodeValue.textContent);
// string-length() - Get length of string
xpath = "string-length(//book[1]/title)";
result = xmlDoc.evaluate(xpath, xmlDoc, null,
XPathResult.NUMBER_TYPE, null);
console.log("Length of first title: " + result.numberValue);
Console Output:
Total books: 3
Book with 'XML': XML Guide
Book starting with 'Web': Web Development
Length of first title: 9
🔹 XPath Result Types
When evaluating XPath expressions, you must specify the expected result type. Choose the appropriate type based on what you need.
Common Result Types:
- ANY_TYPE: Automatically determines type
- NUMBER_TYPE: Returns a number
- STRING_TYPE: Returns a string
- BOOLEAN_TYPE: Returns true/false
- FIRST_ORDERED_NODE_TYPE: Returns first matching node
- ORDERED_NODE_SNAPSHOT_TYPE: Returns all matching nodes
// Different result types
const xmlDoc = /* ... parsed XML ... */;
// Get single node
let result = xmlDoc.evaluate("//book[1]", xmlDoc, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
const firstBook = result.singleNodeValue;
// Get all nodes
result = xmlDoc.evaluate("//book", xmlDoc, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i = 0; i < result.snapshotLength; i++) {
console.log(result.snapshotItem(i));
}
// Get number
result = xmlDoc.evaluate("count(//book)", xmlDoc, null,
XPathResult.NUMBER_TYPE, null);
console.log(result.numberValue);
// Get boolean
result = xmlDoc.evaluate("//book[@id='B001']", xmlDoc, null,
XPathResult.BOOLEAN_TYPE, null);
console.log(result.booleanValue);