diff --git a/CMakeLists.txt b/CMakeLists.txt
index 567b61a..1206e41 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
-project(fun VERSION 0.35.0 LANGUAGES C)
+project(fun VERSION 0.35.1 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
diff --git a/examples/data/catalog.xml b/examples/data/catalog.xml
new file mode 100644
index 0000000..57916e4
--- /dev/null
+++ b/examples/data/catalog.xml
@@ -0,0 +1,32 @@
+
+
+
+ Wireless Keyboard
+ Peripherals
+ 39.99
+
+ US
+ Bluetooth
+ AA
+
+
+
+ 27" Monitor
+ Displays
+ 199.00
+
+ 2560x1440
+ IPS
+ 75Hz
+
+
+
+ USB-C Dock
+ Peripherals
+ 89.50
+
+ 2xHDMI, 3xUSB-A, 1xUSB-C PD
+ 65W
+
+
+
diff --git a/examples/data/employees.xml b/examples/data/employees.xml
new file mode 100644
index 0000000..9ef7114
--- /dev/null
+++ b/examples/data/employees.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ Alice Doe
+ Senior Developer
+ alice@example.com
+
+
+ Bob Roe
+ DevOps Engineer
+ bob@example.com
+
+
+
+
+ Carol Smith
+ Account Executive
+ carol@example.com
+
+
+
diff --git a/examples/data/ns_example.xml b/examples/data/ns_example.xml
new file mode 100644
index 0000000..65ea50b
--- /dev/null
+++ b/examples/data/ns_example.xml
@@ -0,0 +1,11 @@
+
+
+
+ The Art of Fun
+ J. Findeisen
+
+
+ Minimal VM Design
+ A. Dev
+
+
diff --git a/examples/xml_access_catalog.fun b/examples/xml_access_catalog.fun
new file mode 100644
index 0000000..9a31ee8
--- /dev/null
+++ b/examples/xml_access_catalog.fun
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the Fun programming language.
+ * https://fun-lang.xyz/
+ *
+ * Copyright 2025 Johannes Findeisen
+ * Licensed under the terms of the Apache-2.0 license.
+ * https://opensource.org/license/apache-2-0
+ *
+ * Added: 2025-12-09
+ */
+
+/*
+ * Demonstrate reading specific fields from an XML file using
+ * the minimal XML API (root name) and simple string parsing.
+ */
+
+include
+
+path = "./examples/data/catalog.xml"
+xml = XML()
+doc = xml.from_file(path)
+if (doc == 0)
+ print("Failed to load: ")
+ print(path)
+else
+ root = xml.root(doc)
+ print("Root element: ")
+ print(xml.name(root))
+
+ // Show how to access specific fields by quick-and-dirty parsing
+ content = read_file(path) // raw XML text
+ // First product name
+ name = xml.between(content, "", "")
+ // First price value and its currency attribute (extract value, then attribute)
+ price_val = xml.between(content, "")
+ currency = ""
+ if (len(price_val) > 0)
+ currency = xml.between(price_val, "currency=\"", "\"")
+ // strip attribute tag part
+ price_text = xml.between(price_val, ">", "") // until end
+ if (len(price_text) == 0)
+ price_text = price_val
+ else
+ price_text = ""
+
+ print("First product name: ")
+ print(name)
+ print("First price: ")
+ if (len(currency) > 0)
+ print(currency)
+ print(" ")
+ print(price_text)
diff --git a/examples/xml_access_employees.fun b/examples/xml_access_employees.fun
new file mode 100644
index 0000000..c97fcaa
--- /dev/null
+++ b/examples/xml_access_employees.fun
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the Fun programming language.
+ * https://fun-lang.xyz/
+ *
+ * Copyright 2025 Johannes Findeisen
+ * Licensed under the terms of the Apache-2.0 license.
+ * https://opensource.org/license/apache-2-0
+ *
+ * Added: 2025-12-09
+ */
+
+/*
+ * Access selected fields in employees.xml using minimal XML API.
+ */
+
+include
+
+path = "./examples/data/employees.xml"
+xml = XML()
+doc = xml.from_file(path)
+if (doc == 0)
+ print("Failed to load: ")
+ print(path)
+else
+ root = xml.root(doc)
+ print("Root element: ")
+ print(xml.name(root))
+
+ content = read_file(path)
+ // Find the first block and extract its fields
+ first_emp = xml.between(content, "")
+ name = xml.between(first_emp, "", "")
+ role = xml.between(first_emp, "", "")
+ email = xml.between(first_emp, "", "")
+ emp_id = xml.between(first_emp, "id=\"", "\"")
+
+ print("First employee id: ")
+ print(emp_id)
+ print("Name: ")
+ print(name)
+ print("Role: ")
+ print(role)
+ print("Email: ")
+ print(email)
diff --git a/examples/xml_access_ns.fun b/examples/xml_access_ns.fun
new file mode 100644
index 0000000..ae248e5
--- /dev/null
+++ b/examples/xml_access_ns.fun
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the Fun programming language.
+ * https://fun-lang.xyz/
+ *
+ * Copyright 2025 Johannes Findeisen
+ * Licensed under the terms of the Apache-2.0 license.
+ * https://opensource.org/license/apache-2-0
+ *
+ * Added: 2025-12-09
+ */
+
+/*
+ * Access a namespaced XML file and show prefixed element names.
+ */
+
+include
+
+path = "./examples/data/ns_example.xml"
+xml = XML()
+doc = xml.from_file(path)
+if (doc == 0)
+ print("Failed to load: ")
+ print(path)
+else
+ root = xml.root(doc)
+ // With namespaces, the node name may include the prefix, e.g., "ns:library"
+ print("Root element: ")
+ print(xml.name(root))
+
+ content = read_file(path)
+ // Extract first book title and author (namespace prefix bk:)
+ b1 = xml.between(content, "")
+ title = xml.between(b1, "", "")
+ author = xml.between(b1, "", "")
+ print("First book title: ")
+ print(title)
+ print("Author: ")
+ print(author)
diff --git a/lib/io/xml.fun b/lib/io/xml.fun
index 9e9d922..a726638 100644
--- a/lib/io/xml.fun
+++ b/lib/io/xml.fun
@@ -37,3 +37,21 @@ class XML()
// Get node concatenated text content as string.
fun text(this, node)
return xml_text(node)
+
+ // Utility: return substring of s between delimiters a and b.
+ // - If a is not found, returns "".
+ // - If b is an empty string, returns everything after the first occurrence of a.
+ // - If b is not found after a, returns "".
+ fun between(this, s, a, b)
+ i = find(s, a)
+ if (i < 0)
+ return ""
+ i = i + len(a)
+ rest = substr(s, i, len(s) - i)
+ if (len(b) == 0)
+ return rest
+ j = find(rest, b)
+ if (j < 0)
+ return ""
+ return substr(rest, 0, j)
+