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
Add SwiftLibXML to a package and parse your first XML document.
Select matching elements with XPath expressions.
Query namespace-prefixed elements and attributes using XPath.
Notes about the lower-level wrappers that back the public API.