Documentation Language: Swift

Article

Parsing and Traversal

Set up a document, read the root element, and walk the tree.

Parse XML or HTML

Create an XMLDocument from Data, an in-memory UnsafeBufferPointer, or a file path. The default options suppress warning output, disable network access, and ask libxml2 to recover where possible.

import Foundation
import SwiftLibXML

let xmlData = Data("<catalogue><book>Clean Code</book></catalogue>".utf8)
guard let document = SwiftLibXML.XMLDocument(data: xmlData) else {
    // parse failed entirely
    return
}

For HTML input, pass htmlMemoryParser explicitly:

let html = Data("<html><body><p>Hello</p></body></html>".utf8)
guard let document = SwiftLibXML.XMLDocument(data: html, parser: htmlMemoryParser) else {
    return
}

Text Nodes

libxml2 stores the whitespace between sibling elements as text nodes. When you iterate children or descendants, those text nodes appear alongside element nodes and report the name "text". This is correct and expected libxml2 behaviour.

To work only with named elements, filter by name:

for child in root.children where child.name != "text" {
    print(child.name)
}

Alternatively, an XPath expression such as "//book" already selects element nodes exclusively and requires no filtering.

Work from the Root Element

rootElement gives you the root node as an XMLElement. From there you can inspect:

Choose a Traversal Strategy

XMLElement conforms to Sequence, so iterating over an element performs a depth-first pre-order walk using XMLElement.Iterator. When you only need the current level, use levelIterator() or siblings.

XMLDocument is itself a Sequence whose iterator visits every node in the document in depth-first pre-order, including text nodes:

for node in document {
    // visits every node, including whitespace text nodes
    print("\(node.name): \(node.content.prefix(40))")
}

tree exposes XMLTree, which yields tuples containing the nesting level, the current node, and its parent. That is useful when you need to render or analyse indentation-sensitive output without recomputing ancestry:

for (level, node, _) in document.tree {
    let indent = String(repeating: "  ", count: level)
    print("\(indent)\(node.name)")
}

Read Attributes

Use attribute(named:) to read an attribute value by name:

let id = element.attribute(named: "id") ?? "none"

Use attribute(named:namespace:) when the attribute carries a namespace URI:

let lang = element.attribute(named: "lang", namespace: "http://www.w3.org/XML/1998/namespace")

Iterate all attributes via attributes:

for attribute in element.attributes {
    print("\(attribute.name)")
}

See Also

Essentials

A
Getting Started with SwiftLibXML

Add SwiftLibXML to a package and parse your first XML document.

A
XPath Queries

Select matching elements with XPath expressions.

A
Working with Namespaces

Query namespace-prefixed elements and attributes using XPath.

A
Implementation Notes

Notes about the lower-level wrappers that back the public API.