This should probably be done in PL / SQL, which I don't know, but I wanted to see how far I can get it with pure SQL. This only replaces the first appearance of the code, so you have to somehow run it several times.
select regexp_replace(s, '&#([0-9]+);', u) from (select s, unistr('\0' || REPLACE(TO_CHAR(TO_NUMBER(c), 'xxxx'), ' ', '')) u from (select s, regexp_replace(s, '.*&#([0-9]+);.*', '\1') c from (select 'Hallöle slovenčina' s from dual)))
Or less readable, but more convenient:
SELECT REGEXP_REPLACE(s, '&#([0-9]+);', unistr('\0' || REPLACE(TO_CHAR(TO_NUMBER(regexp_replace(s, '.*?&#([0-9]+);.*$', '\1', 1, 1)), 'xxxx'), ' ', '')), 1, 1) FROM (SELECT 'Hallöle slovenčina č Ė' s FROM DUAL)
This (updated) version correctly replaces the first occurrence. You need to apply it until all of them are replaced.
source share