Thanks, Liam. Appreciate the confirmation that I wasn't missing an option. Going to go try do-until and then typeswitch if I haven't got the brain cells for do-until. On Tue, Apr 28, 2026, at 02:46, Liam R. E. Quin wrote:
On Mon, 27 Apr 2026 17:26:25 -0400 Graydon Saunders via BaseX-Talk <basex-talk@mailman.uni-konstanz.de> wrote:
let $test as element() := <p>First <span><span><span>word</span></span></span> was excited.</p> return $test update {(.//span[empty(@*)]) ! (replace node . with ./node()) }
Here the first item will be the first span, and it'll be replaced with its contents, i.e. node(), which is a span element that in turn contains a span element.
You need to replace with the result of replacing, but that indeed means recursion.
Strictly speaking this approach isn't possible with XQuery Update, as an expression can't see the result of an update, but everyone hated that restriction and i doubt BaseX enforces it.
Sometimes i use a "visitor" module to simulate xsl:apply-templates for this sort of change, although calling out to XSLT via transform() would work too, as would the recursive function with typeswitch you already wrote :)
liam
-- Liam Quin: Delightful Computing - Training and Consultancy in XSLT / XML Markup / Typography / CSS / Accessibility / and more... Outreach for the GNU Image Manipulation Program Vintage art digital files - fromoldbooks.org