7.7.1. PUGIXML-01 — Parsing & Navigation

This tutorial covers parsing XML documents and navigating their node trees using pugixml/PUGIXML_boost.

7.7.1.1. Setup

Import the module:

require pugixml/PUGIXML_boost

PUGIXML_boost re-exports the core pugixml module, so a single require gives you everything.

7.7.1.2. Parsing from a string

parse_xml parses an XML string inside a block. The document is freed automatically when the block returns — no manual delete needed:

let xml = "<greeting lang=\"en\">Hello!</greeting>"

parse_xml(xml) <| $(doc, ok) {
    if (!ok) { return; }
    let root = doc.document_element
    print("{root.name}: {root.text as string}\n")
}
// greeting: Hello!

7.7.1.3. Loading from a file

open_xml loads a file with the same RAII pattern:

open_xml("tutorials/dasPUGIXML/books.xml") <| $(doc, ok) {
    if (!ok) { return; }
    let root = doc.document_element
    print("root: {root.name}\n")
}

7.7.1.4. Iterating children

for_each_child iterates over all child elements of a node using a block callback. Pass an optional name to filter by tag:

// all children
root |> for_each_child() <| $(ch) {
    print("<{ch.name}>\n")
}

// only <setting> children
root |> for_each_child("setting") <| $(ch) { ... }

each_child returns a lazy iterator for use in for loops — same traversal, different syntax:

for (ch in each_child(root)) {
    print("<{ch.name}>\n")
}

for (ch in each_child(root, "setting")) { ... }

for_each_attribute iterates attributes with a block callback:

node |> for_each_attribute() <| $(a) {
    print("{a.name} = {a as string}\n")
}

each_attribute is the iterator alternative:

for (a in each_attribute(node)) {
    print("{a.name} = {a as string}\n")
}

7.7.1.5. Quick accessors

Helper functions read child text and attribute values with defaults for missing data:

Function

Returns

node_text(n, "tag")

Text of child <tag> as string

node_attr(n, "key")

Attribute value as string

node_attr_int(n, "key")

Attribute as int

node_attr_float(n, "key")

Attribute as float

node_attr_bool(n, "key")

Attribute as bool

All accept an optional default value:

let name  = node_text(node, "name", "unknown")
let price = node_attr_float(node, "price", 0.0)

7.7.1.6. Typed access with is/as

operator [] on xml_node returns an xml_attribute. The is and as operators convert attributes and text values to typed values:

// Attribute access
let x_attr = node["x"]           // xml_attribute
let x_val  = node["x"] as int    // 10
let label  = node["label"] as string

// Text access
let count = child_node.text as int
let ratio = child_node.text as float

is returns true when the attribute or text node exists (non-empty).

7.7.1.7. Practical example

Combining these tools to read a book catalog:

open_xml("books.xml") <| $(doc, ok) {
    if (!ok) { return; }
    doc.document_element |> for_each_child("book") <| $(book) {
        let title = node_text(book, "title")
        let isbn  = book["isbn"] as string
        let price = child(book, "price").text as float
        print("{title}{isbn}, ${price}\n")
    }
}