XML und Sonderzeichen in C++ (immer noch offen!!)



  • Hallo,

    ich lade mit der Funktion NodeValue Daten aus einen XML Node in ein AnsiString rein.
    Wie bekomm ich es hin, dass die Sonderzeichen nicht mehr codiert sind, also nicht mehr %7E oder so lauten?

    MfG
    TheCaleb



  • Hallo

    Das ist höchstwahrscheinlich UTF8. Du must also UTF8 in Ascii umwandeln, eine solche Funktion hat der Builder (zumindestens in meinem Builder 5) selber nicht. Du must also eine externe Bibliothek dafür suchen und einbinden. Ich glaube zum Beispiel das Indy-Package bietet sowas.

    bis bald
    akari



  • Vielen Dank aber wo finde ich das Indy-Package oder wie binde ich das ein?



  • Hallo

    Wenn es bei deinem Builder nicht schon dabei ist, dann kannst du das hier herunterladen. Allerdings nur Version 9, Version 10 läuft auf dem Builder nicht.
    Einbinden siehe die mitgelieferte Readme-Datei.

    bis bald
    akari



  • Danke, ich sehe gerade, dass es schon drin ist!
    Welche Funktion genau muss ich denn dazu verweden??



  • Weißt du keine Funktion, akari?



  • Hallo

    Ich habe vermutet das es dort eine solche Funktion geben könnte. Du must schon selber die Doku zum Indy-Package selber durchsuchen.
    Wenn du keine findest must du ein anderes Package nehmen das sowas anbietet.

    Ich weiß das zum Beispiel TnT eine Funktion Tntsystem::UTF8Decode hat.
    Möglicherweise findest du noch irgendwo eine alte Version des Packages, die noch Freeware ist.

    bis bald
    akari



  • Wie wärs, wenn du den Text aus dem Node erstmal in einen WideString packst. Den könntest du dann weiter versuchen in einen AnsiString umzuwandeln (wenn überhaupt nötig).



  • Hallo

    Du kannst zwar AnsiString und WideString miteinander konvertieren (über die Konstruktoren) aber dabei wird keine UTF8-Codierung berücksichtigt.

    bis bald
    akari



  • Auch nicht wenn man WideCharToMultiByte etc. verwendet?
    Ich muß zugeben, dass ich wenig Erfahrung damit habe, da mir UTF8-kodierte Strings bisher kaum untergekommen sind.
    Ich habe aber das hier gefunden und das sieht für mich ganz gut aus.
    http://www.swissdelphicenter.ch/de/showcode.php?id=1692



  • Hallo

    Nein den die von dir gezeigte Umwandlung ist ja gerade Codepage-abhängig. Hast du einen Widestring mit einem deutschen "ä", kannst du diesen auf einem System mit einer Codepage ohne dem "ä" nicht umwandeln... (ä kann durch beliebige Zeichen aus Arabisch, Hebräisch, Kyrillisch ersetzt werden).
    Erst mit UTF8 kannst du die Unicode-Zeichen der meisten Sprachen unabhängig von Codepages umwandeln. Das bedeutet aber auch das die so kodierten AnsiStrings aus Kombinationen von Zeichen bestehen die ohne Rückumwandlung keinen Sinn ergeben, selbst wenn die Zeichen selber einfach in das Wide-Äquivalent umgewandelt werden.

    Hier mal die entsprechende Funktion aus Tnt um UTF8-AnsiString in WideString umzuwandeln. (Ich hoffe ich habe alles erwischt)

    function Utf8Decode(const S: UTF8String): WideString;
    
        function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: Cardinal;
          Source: PAnsiChar; SourceBytes: Cardinal): Integer;
        var
          i, count: Cardinal;
          c: Byte;
          wc: Cardinal;
        begin
          if Source = nil then
          begin
            Result := 0;
            Exit;
          end;
          Result := -1;
          count := 0;
          i := 0;
          if Dest <> nil then
          begin
            while (i < SourceBytes) and (count < MaxDestChars) do
            begin
              wc := Cardinal(Source[i]);
              Inc(i);
              if (wc and $80) <> 0 then
              begin
                if i >= SourceBytes then Exit;          // incomplete multibyte char
                wc := wc and $3F;
                if (wc and $20) <> 0 then
                begin
                  c := Byte(Source[i]);
                  Inc(i);
                  if (c and $C0) <> $80 then Exit;      // malformed trail byte or out of range char
                  if i >= SourceBytes then Exit;        // incomplete multibyte char
                  wc := (wc shl 6) or (c and $3F);
                end;
                c := Byte(Source[i]);
                Inc(i);
                if (c and $C0) <> $80 then Exit;       // malformed trail byte
    
                Dest[count] := WideChar((wc shl 6) or (c and $3F));
              end
              else
                Dest[count] := WideChar(wc);
              Inc(count);
            end;
            if count >= MaxDestChars then count := MaxDestChars-1;
            Dest[count] := #0;
          end
          else
          begin
            while (i < SourceBytes) do
            begin
              c := Byte(Source[i]);
              Inc(i);
              if (c and $80) <> 0 then
              begin
                if i >= SourceBytes then Exit;          // incomplete multibyte char
                c := c and $3F;
                if (c and $20) <> 0 then
                begin
                  c := Byte(Source[i]);
                  Inc(i);
                  if (c and $C0) <> $80 then Exit;      // malformed trail byte or out of range char
                  if i >= SourceBytes then Exit;        // incomplete multibyte char
                end;
                c := Byte(Source[i]);
                Inc(i);
                if (c and $C0) <> $80 then Exit;       // malformed trail byte
              end;
              Inc(count);
            end;
          end;
          Result := count + 1;
        end;
    
    var
      L: Integer;
      Temp: WideString;
    begin
      Result := '';
      if S = '' then Exit;
      SetLength(Temp, Length(S));
    
      L := Utf8ToUnicode(PWideChar(Temp), Length(Temp)+1, PAnsiChar(S), Length(S));
      if L > 0 then
        SetLength(Temp, L-1)
      else
        Temp := '';
      Result := Temp;
    end;
    

    bis bald
    akari



  • Hm leider wurde mein Problem immer noch nicht behoben!
    Also wenn ich den Node mit der Funktion NodeValue auslesen lasse und den dann mit der utf8encode bzw utf8toansi Funktion encoden lasse, geschieht leider nichts, also die %7E Zeichen oder so bleiben drin.

    Was nun?!



  • Hallo

    Dann ist es wohl kein richtiges UTF8-Zeichen. Vielleicht soll es so sein? Weist du denn was es uncodiert bedeuten soll?

    bis bald
    akari



  • Ich meine das %7E müsste ein ° sein.
    Oder %20 halt wie bekannt ein Leerzeichen usw...
    Wollste nun etwa da drauf hinaus, eine Funktion zu schreiben um alle Zeichen zu ersetzen?



  • du brauchst einen URI Encoder da die Zeichen Escaped sind.
    z.B. das %7E ist ein ~ Zeichen

    hier eine kleine Beschreibung
    http://www.w3.org/International/O-URL-code.html

    und hier die Lösung:
    http://www.codeguru.com/cpp/i-n/internet/http/article.php/c12759/



  • Vielen Danke, Borland hat die Funktion URLDecode() bereits und die erfüllt meinen Wunsch! 🙂

    MfG
    TheCaleb



  • Hm die URLDecode- Funktion ist bei der 2006er Version von Borland nur noch im Indy- Package enthalten und ich habe keine Ahnung, wie ich das anwenden sollte.
    Zudem fiel mir auf, dass Ä Ö Ü garnicht decodiert werden.
    Gibt es andere Funktionen die das können, also UTF-16 decodieren?!
    Oder gibt es vielleicht sofort ne Möglichkeit über XML Funktionen von einem NodeValue oder so auf einen dekodierten String zu kommen?



  • @ Akari hast du keine Idee, welche Funktion ich nutzen kann oder lässt du diesen Beitrag absichtlich links liegen, da dieses Thema schonmal behandelt wurde?
    Ich brauche halt Hilfe, da ich keine Funktionen finden kann oder die von Indy(leider ohne ÄÖÜ) nicht einbinden kann...

    Bitte helft mir doch weiter!! 🙄



  • URLDecode() war doch schon immer nur im Indy-Package mit drin. Das sollte doch auch im 2006er Builder mit dabei sein.



  • Ja ist es auch aber ich versteh nicht so ganz, wie ich diese Funktion einbinden kann, denn sonst ging das immer einfach so, dass ich diese Funktion einfach anwenden musste.
    Gibt es nicht auch noch zufällig andere Funktionen, die ebenfalls auch das Ä Ü Ö dekodieren?


Anmelden zum Antworten