Getting Started

Query a Document with XPath

In this tutorial you compile XPath expressions to select elements, use predicates to narrow results, and query namespace-prefixed XML.

XPath selects element nodes exclusively, which means you do not need to filter out whitespace text nodes from the results.

10 mins Estimated Time

Section 1

Select Elements with XPath

xpath(_:namespaces:defaultPrefix:) compiles an XPath expression and returns an XMLPath collection. Because XMLPath conforms to RandomAccessCollection, you can use the full range of Swift collection operations on the result.

Step 1

Parse the XML source and compile a simple XPath expression to select all title elements.

XPathQuery.swift
1import Foundation
2
3func queryTitles() {
4 let xml = """
5 <?xml version="1.0" encoding="UTF-8"?>
6 <catalogue>
7 <book id="1">
8 <title>Clean Code</title>
9 <author>Robert C. Martin</author>
10 </book>
11 <book id="2">
12 <title>The Swift Programming Language</title>
13 <author>Apple Inc.</author>
14 </book>
15 </catalogue>
16 """
17
18 guard let document = XMLDocument(data: Data(xml.utf8)) else { return }
19
20 // Select all title elements anywhere in the document.
21 // XPath returns element nodes only — no text-node filtering needed.
22 if let titles = document.xpath("//title") {
23 for title in titles {
24 print(title.content)
25 }
26 }
27 // Clean Code
28 // The Swift Programming Language
29}

Step 2

Add an attribute predicate to select only the book with id="1".

XPathQuery.swift
1import Foundation
2
3func queryTitles() {
4 let xml = """
5 <?xml version="1.0" encoding="UTF-8"?>
6 <catalogue>
7 <book id="1">
8 <title>Clean Code</title>
9 <author>Robert C. Martin</author>
10 </book>
11 <book id="2">
12 <title>The Swift Programming Language</title>
13 <author>Apple Inc.</author>
14 </book>
15 </catalogue>
16 """
17
18 guard let document = XMLDocument(data: Data(xml.utf8)) else { return }
19
20 // An attribute predicate narrows the selection to a specific book.
21 if let books = document.xpath("//book[@id='1']") {
22 for book in books {
23 let title = book.children.first(where: { $0.name == "title" })?.content ?? ""
24 print(title)
25 }
26 }
27 // Clean Code
28}

Section 2

Query Namespaced Elements

XPath requires an explicit prefix for every namespace in an expression, even when the document uses a default namespace.

Register the prefix-to-URI mapping by passing a [(prefix: String, href: String)] array to the namespaces: parameter.

Step 1

Parse an Atom feed and use a namespace-aware XPath expression to select atom:title elements.

XPathQuery.swift
1import Foundation
2
3func queryAtomTitles() {
4 let xml = """
5 <?xml version="1.0" encoding="UTF-8"?>
6 <feed xmlns:atom="http://www.w3.org/2005/Atom">
7 <atom:entry>
8 <atom:title>SwiftLibXML 2.0 Released</atom:title>
9 <atom:updated>2026-01-15T00:00:00Z</atom:updated>
10 </atom:entry>
11 </feed>
12 """
13
14 guard let document = XMLDocument(data: Data(xml.utf8)) else { return }
15
16 // Register the namespace prefix explicitly.
17 let ns: [(prefix: String, href: String)] = [
18 ("atom", "http://www.w3.org/2005/Atom")
19 ]
20 if let titles = document.xpath("//atom:title", namespaces: ns) {
21 for title in titles {
22 print(title.content)
23 }
24 }
25 // SwiftLibXML 2.0 Released
26}