Спустя полторы недели изучения документации, статей и видеоуроков я нашел следующее решение, которое сводится к тому, чтобы привести xml к text
Допустим у меня есть корень User и его потомки ноды Action
select unnest(xpath('//user', xml_test_f))::text from xml_test where id = 3;
<user userid="1" login="user">
<action billid="22" name="REPLACEMENT">
<status>CLOSED</status>
</action>
<action billid="11" name="REPLACEMENT"><status>OPEN</status></action><action/>
</user>
В конце списка действий при первоначальном создании документа вставляется закрытая пустая нода .
Создается следующая функция
create or replace function addNode(xmlId integer, newNode xml)
returns void as
$BODY$
declare oldXml text;
begin
select unnest(xpath('//user', xml_test_f))::text into oldXml from xml_test where id = 3;
update xml_test set xml_test_f=xml(REPLACE(oldXml::text,'<action/>', newNode::text ||'<action/>')) where id = xmlId;
end
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
В которой мы выбираем дерево от пользователя и редактируем его. При редактировании закрытая нода заменяется на ноду поданную на вход + закрытую ноду newNode::text ||''.
Теперь эту функцию можно использовать
Select addNode(3, xmlelement(name action, xmlattributes('11' as billId, 'REPLACEMENT' as name),
xmlelement(name status, 'OPEN')));