Finalmente encontré una solución y la clave fue usar la función XMLTable(). Aquí está mi código:
declare
v_inXML xmltype;
v_tmpXML xmltype;
v_withIdXML xmltype;
v_outXML xmltype;
BEGIN
v_inXML := XMLType('<root><x a="a"/><x a="b"/><x a="c"/></root>');
v_withIdXML := XMLType('<root/>');
v_outXML := XMLType('<root/>');
for c_rec in (
select *
from XMLTable('for $i in /root/x
return $i'
passing v_inXML
columns x xmltype path '/x'
)
)
loop
select insertchildxml(c_rec.x,'//x', '@b', pckg_ent_pk_seq.nextval) into v_tmpXML from dual;
select insertchildxml(v_withIdXML, '/root', 'x', v_tmpXML) into v_withIdXML from dual;
end loop;
select updatexml(v_outXML, '/root', v_withIdXML) into v_outXML from dual;
dbms_output.put_line(v_outXML.getClobVal());
END;
Y el resultado es:
<root><x a="a" b="92"/><x a="b" b="93"/><x a="c" b="94"/></root>