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);

🧠 Test Your Knowledge

What does the XPath expression "//book" select?