SET search_path TO xml; -- Write functions using the descendant axe... create table a (i int, data doc, targ_path xml.path, new_node node, add_mode add_mode); insert into a values (1, '', '/root//x/b', '', 'r'), (2, '', '/root//x/b', '', 'b'), (3, '', '/root//x/b', '', 'a'), (4, '', '/root//x//b', '', 'r'), (5, '', '/root//x//b', '', 'a'), (6, '', '//x//b', '', 'r'), (7, '', '//x//b', '', 'a'), (8, '', '/root//x/b', '', 'i'); -- Specifically, addition must not take place multiple times for the same node. insert into a values (9, '', '/root//x//b', '', 'b'), (8, '', '/root//x//b', '', 'i'), (10, '', '//x//b', '', 'b'), (11, '', '//x//b', '', 'i'), (12, '', '/root//x//b', '', 'i'); select node_debug_print(data), targ_path, add_mode, new_node, node_debug_print(xml.add(data, targ_path, new_node, add_mode)) from a order by a.i; -- Add a node that matches the xpath. update a set new_node=''; select node_debug_print(data), targ_path, add_mode, new_node, node_debug_print(xml.add(data, targ_path, new_node, add_mode)) from a order by a.i; -- Add a subtree that contains matching nodes (i.e. infinite recursion could take place). update a set new_node=''; select node_debug_print(data), targ_path, add_mode, new_node, node_debug_print(xml.add(data, targ_path, new_node, add_mode)) from a order by a.i; -- Similar to the previous one, just a document fragment is added instead of a single (though compound) node. update a set new_node=''; select node_debug_print(data), targ_path, add_mode, new_node, node_debug_print(xml.add(data, targ_path, new_node, add_mode)) from a order by a.i; -- And finally test node removal drop table a; create table a (i int, data doc, targ_path xml.path); insert into a values (1, '', '/root/x/b'), (2, '', '/root//x/b'), (3, '', '/root//x/b'), (4, '', '/root//x//b'), (5, '', '/root//x//b'), (6, '', '/root//x//b'), (7, '', '/root//x//b'), (8, '', '/root//x//b'), (9, '', '/a/b//@id'), (10, '', '//@id'), (11, '', '//@*'); select node_debug_print(data), targ_path, node_debug_print(xml.remove(data, targ_path)) from a order by a.i; drop table a; select xml.remove('', '/a/b/c'); select xml.add( '', '/a', '', 'b' );