Som @kfinity foreslog, er dette relateret til CLOB-håndtering, men også til hvordan dbms_output
arbejder. Du læser CLOB i bidder af 32k og skriver hver af disse bidder ud med put_line()
, som tilføjer et nylinjetegn efter hver 32k chunk. Disse er ikke justeret med nogen eksisterende linjeskift i dit XML-dokument, så du får de originale skift, derefter ekstra - som vises noget tilfældigt og midt i teksten, men faktisk er på forudsigelige steder.
En oplagt løsning er at skifte fra put_line()
til put()
, men det vil bryde den maksimale bufferstørrelse og kaste noget som "ORU-10028:linjelængdeoverløb, grænse på 32767 bytes pr. linje".
I stedet for at læse i faste 32k bidder, kunne du læse en linje ad gangen; CLOB'en forstår ikke rigtig linjer som sådan, men du kan kigge efter linjeskift, sådan noget som:
WHILE pos < v_clob_length LOOP
-- read to next newline if there is one, rest of CLOB if not
if dbms_lob.instr(v_clob, chr(10), pos) > 0 then
amount := dbms_lob.instr(v_clob, chr(10), pos) - pos;
dbms_lob.read(v_clob, amount, pos, buffer);
pos := pos + amount + 1; -- skip newline character
else
amount := 32767;
dbms_lob.read(v_clob, amount, pos, buffer);
pos := pos + amount;
end if;
dbms_output.put_line(buffer);
END LOOP;
if
leder efter et linjeskifttegn efter den aktuelle position. Hvis den finder en, så beregnes mængden som antallet af tegn fra den nuværende position til den nye linje (eller rettere minus én - da du ikke ønsker selve den nye linje), den læser så mange tegn og justerer derefter positionen med mængden læst plus én (for at springe den nye linje over - som du ikke ønsker/bruger som put_line()
tilføjer en stadig).
Hvis den ikke finder en, så læser den op til 32k - forhåbentlig kun én gang; hvis der er mere end det, kan tegn tilbage uden linjeskift, så læser den endnu en gang, men tilføjer stadig den ekstra nye linje og bryder den linje. Du kan ikke gøre meget ved det ved at bruge dbms_output
dog skal du skifte til utl_file
at skrive til serveren i stedet for at spoole til klienten.