Anmelden

View Full Version : DB2 / SQL / String auf gültige Zeichen prüfen



Seiten : [1] 2 3

rissling
18-03-16, 09:58
Hallo Forum,

ich habe folgendes Problem:

ich lese aus einer DB2-Tabelle Daten, die in XML umgesetzt werden. Dafür erzeuge ich mit Hilfe von SQL eine Zwischendatei. Ein Tag sieht so aus:

Exec Sql
Insert into temp
(XMLSTRING)
values(
XMLSERIALIZE(
XMLDOCUMENT(
XMLELEMENT(NAME "ingredients", trim(Char(:variable)))
)
AS VARCHAR(5000) CCSID 1208
));
Enthält "variable" ungültige Zeichen, fällt mein SQL mit einem SQLCOD von -20377 auf die Nase.
Wie schaffe ich es, ungültige Zeichen vor dem SQL herauszufiltern? Oder gibt es eine SQL-Funktion, die ich nur nicht finden kann? ;-)

Fehlerbeschreibung hier:
https://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/com.ibm.db2z10.doc.codes/src/tpc/n20377.dita
Da steht euch eine Liste der gültigen Zeichen.

Gruß,
Frederik

Fuerchau
18-03-16, 10:20
Die Frage ist, was sind ungültige Zeichen?
In einem Element (Attribut oder Knoten) darf z.B. natürlich kein "<" vorkommen, da damit wieder XML eingeleitet wird.
Hierfür benötigst du eine SQL-Funktion, die dir die Zeichen übersetzt.
Aus "<" wird dann z.B. "&lt;", aus dem "&" dann "&amp;" usw.
Nicht druckbare Zeichen (Hexwerte) müssen dann in Pseudo-Unicode (ich glaube "#nnnn;" o.ä.) übersetzt werden.
Umgedreht, beim Einlesen benötigst du dann eine Rückübersetzung.
Leider gibt es dafür tatsächlich keine Standard-SQL-Funktion, dafür musst du dir eine schreiben (lassen).

Fuerchau
18-03-16, 10:26
Genaueres kannst du auch hier nachlesen:
https://wiki.selfhtml.org/wiki/Referenz:HTML/Zeichenreferenz

rissling
18-03-16, 10:31
Ungültige Zeichen sind hier Zeichen, die SQL anmeckert (siehe Link oben - da stehen ja im Text die erlaubten Zeichen). Das Problem ist, dass der gesamte Befehl scheitert und mir der Tag in der XML-Datei fehlt.

Ich brauche auch gar nicht den großen Aufwand über Pseudocode; es würde mir reichen, die ungültigen Zeichen mit Spaces zu ersetzen, da ich keine Rückübersetzung brauche. Wie stelle ich das an?

Hintergrund: Hier geht es um Zutatentexte, die von einer Waage aufs Etikett gedruckt werden. Die Daten werden von der AS/400 in XML gewandelt und dann per FTP an die Waage übertragen. Besser als gar keinen Text auszudrucken ist also, die ungültigen Zeichen einfach weg zu lassen.

Pikachu
18-03-16, 10:47
Wie wärs mit XLATE in RPG ?

Fuerchau
18-03-16, 10:52
Mir ist nicht bekannt, dass XLATE aus 1 Zeichen mehr als 1 Zeichen ersetzt.
Der Vorgang ist da schon etwas komplexer.

rissling
18-03-16, 10:56
Für %XLATE müsste ich aber wissen, WAS ich ersetzen soll. Leider kann in einem einzelnen Zeichen des Strings irgendein Schrott-Hexwert drin stehen. Besser wäre also mit %CHECK oder so zu prüfen, ob die Zeichen gültig sind. Da das aber ne ganze Latte sind (https://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/com.ibm.db2z10.doc.codes/src/tpc/n20377.dita) geht das so auch nicht. Ich wüßte auch gar nicht, wie ich da Hex-Werte angebe...

Pikachu
18-03-16, 10:57
Macht er auch nicht. Muß aber auch nicht, oder? ;)
Ansonsten eben mehrmals %SCAN und %REPLACE oder %SCANRPL (sofern verfügbar).


Mir ist nicht bekannt, dass XLATE aus 1 Zeichen mehr als 1 Zeichen ersetzt.
Der Vorgang ist da schon etwas komplexer.

Fuerchau
18-03-16, 11:08
Siehe obigen Link für die HTML's.

d MySource s 1000 varying
d MyDest s 2000 varying
d Ind s 5i 0

// grobes Beispiel
MyDest = '';
for Ind=1 to %len(MySource);
select;
when %subst(MySource:1:1) < *blank
or %subst(MySource:1:1) >= x'FE';
MyDest += RoutineHexToHtml(%subst(MySource:1:1)); // #xNNNN, N = 0-9A-F
when %subst(MySource:1:1) = '&';
MyDest += '&amp;';
when %subst(MySource:1:1) = '<';
MyDest += '&lt;';
when %subst(MySource:1:1) = '>';
MyDest += '&gt;';
:
:
other;
MyDest += %subst(MySource:1:1);
endsl;
endfor;

rissling
18-03-16, 15:28
Ich bekomms nicht hin. Ich habe es so probiert:

//-----------------------------------------------------------------------
// XML-String prüfen
//-----------------------------------------------------------------------
dcl-proc XMLConvert;
dcl-pi *N;
$string ucs2(5000);
end-pi;


dcl-s #i zoned(4:0);
dcl-s $ch char(1);
dcl-s $temp ucs2(5000);


$temp = '';
for #i = 1 to %len($string);
$ch = %char(%subst($string:#i:1));
if $ch = x'09'
or $ch = x'0A'
or $ch = x'0D'
or ($ch >= x'20' and $ch <= x'D7FF')
or ($ch >= x'E000' and $ch <= x'FFFD')
or ($ch >= x'100000' and $ch <= x'10FFFF');
$temp = $temp + %subst($string:#i:1);
endif;
endfor;
$string = $temp;
return;
end-proc;
Der Ergebnisstring ist aber immer leer. Wenn ich mit Debug durchsteppe, scheint er die Zeile
$temp = $temp + %subst($string:#i:1); gar nicht auszuführen.

Wahrscheinlich sehe ich den Wald aber vor lauter Bäumen nicht mehr. ;-)
Ich geh jetzt mal ins Wochenende und mache am Montag weiter :-)