I was thinking of something like this:
; Replacements map
Local $mReplace[]
$mReplace['1104'] = 'nbs'
$mReplace['1105'] = 'quo'
$mReplace['1106'] = 'apo'
$mReplace['1107'] = 'nbs'
$mReplace['1108'] = 'nbs'
$sData = '<trans-unit translate="no" id="bf7c95b8-58a9-4352-988c-7679b8942d49"><source><x id="1104"/><x id="1105"/>' & _
'</source></trans-unit><trans-unit id="47e1477a-98e9-4759-997f-a4e722e63ce5"><source>The quick brown fox<x id="1106"/>' & _
'ABCDE</source><seg-source><mrk mtype="seg" mid="180">Jumps over the lazy dog<x id="1106"/>FGHIJ</mrk></seg-source>' & _
'<target><mrk mtype="seg" mid="180"/></target><sdl:seg-defs><sdl:seg id="180"/></sdl:seg-defs></trans-unit>' & _
'<trans-unit translate="no" id="aa1f3715-586f-437b-8d7b-d2324b27fc8d"><source><x id="1107"/><x id="1108"/></source></trans-unit>'
Local $sPattern, $aRegEx
Local $iOffset = 1
Local $aKeys = MapKeys($mReplace)
For $vKey In $aKeys
$sPattern = '<x id="' & $vKey & '"'
$aRegEx = StringRegExp($sData, $sPattern, 1, $iOffset)
If Not @error Then
$iOffset = @extended
$sData = StringRegExpReplace($sData, '^(.{' & $iOffset - StringLen($sPattern) - 1 & '})' & $sPattern & '(.*?)', '$1<x id="' & $vKey & '" ctype="' & $mReplace[$vKey] & '"$2')
EndIf
Next
MsgBox(0, '', $sData)
This is more optimized than a simple string replace because with each replace the offset it's increased so there will be no more parsing of that part of the string where replaces already occurs. The replace is also fast because it jumps at the exact position where the next replace will be done. Your replacement rules are vaguely described so this it's just a proof of concept and have some requirements like the IDs to be in order and without duplicates but a more refined code might be written.