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



  • 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?



  • Also wie ich in der beigehängten Borland Hilfe sehen kann, ist die URLDecode keine Funktion, sondern eine Methode geworden, doch wie konnte man nochmal ein Object einer Klasse erstellen also wie konnte man die Klasse nochmal einbinden?

    Borland Hilfe:

    Indy.Sockets version 10.1.1.

    URLDecode Method

    Declaration
    class function URLDecode(
    ASrc: string
    ): string;
    Parameters
    Parameters Description
    ASrc URL-encoded string to be decoded.

    Returns
    String - The un-encoded ASCII representation of the URL.
    Summary
    Converts a URL-Encoded string to a US-ASCII string.
    Description
    URLDecode is a string class function that converts the URL-encoded string in ASrc to its representation in the US-ASCII character set. URLDecode is based on the URL character encoding rules as described in the Internet Standards document:
    RFC 1738 - Uniform Resource Locators (URL)

    URLDecode can used to reverse any string encoding performed using URLEncode.

    URLDecode converts all occurrances of the '+' character to ' ' (Space) (Decimal 32). URLDecode reads any values represented as a hexadecimal character triplet consisting of the "%" character followed by the two-digit hexadecimal value for the octet, and returns the value to its US-ASCII representation.

    Example
    AString := TIdURI.URLDecode(AURLString);
    See Also
    TIdURI.URLEncode
    Class
    TIdURI



  • Hallo,

    Du mußt einfach ein Objekt vom Typ TIdURI erstellen. Dann kannst du dessen Membermethode nutzen. Etwa so

    TIdURI* uri = new TIdURI;
    AnsiString decode = uri->URLDecode(code);
    // delete uri dann nicht vergessen
    


  • Danke, ich habe jetzt folgendes geschrieben:

    TIdURI* uri = new TIdURI('asd');
    uri->URLDecode("ads");
    

    Doch angeblich müsste ich noch einen weiteren Parameter angeben, erst TMetaClass, dann erst mein String:

    [C++ Error] Unit1.cpp(70): E2034 Cannot convert 'char *' to 'TMetaClass *'
    [C++ Error] Unit1.cpp(70): E2342 Type mismatch in parameter 'vmt' (wanted 'TMetaClass *', got 'char *')

    Doch was ist eine Variabel von TMetaClass oder so?!
    Bzw wie müsste das dann aussehen?



  • Ich brauche immer noch Hilfe



  • Ok, ich hab mir mal die Headerdatei dazu angeschaut. Die Deklaration sieht so aus.

    static AnsiString __fastcall URLDecode(TMetaClass* vmt, AnsiString ASrc);
    

    Wie man sieht, ist die Funktion statisch (benötigt also kein zusätzliches Objekt) und der Konstruktor benötigt zwei Parameter.
    Der Aufruf müsste also so aussehen (ungetestet)

    TIdURI::URLDecode(__classid(TIdURI), "ads");
    


  • Wenn ich den Aufruf

    TIdURI::URLDecode(__classid(TIdURI), "ads");
    

    schreibe, dann treten folgende Fehler auf:

    [Linker Error] Error: Unresolved external 'Iduri::TIdURI::' referenced from ...UNIT1.OBJ
    [Linker Error] Error: Unresolved external '__fastcall Iduri::TIdURI::URLDecode(System::TMetaClass *, System::AnsiString)' referenced from ...UNIT1.OBJ

    Wenn ich dann die Indy10 einbinde, dann treten mehrere Fehler in der Datei HTTPApp.hpp auf, diese Datei nutze ich hingegen nicht bewußt:

    [C++ Error] Httpapp.hpp(94): E2293 ) expected
    [C++ Error] Httpapp.hpp(983): E2189 extern variable cannot be initialized
    [C++ Error] Httpapp.hpp(983): E2449 Size of 'ExtractHeaderFields' is unknown or zero
    [C++ Error] Httpapp.hpp(983): E2188 Expression syntax
    [C++ Error] Httpapp.hpp(983): E2293 ) expected
    [C++ Error] Httpapp.hpp(984): E2189 extern variable cannot be initialized
    [C++ Error] Httpapp.hpp(984): E2449 Size of 'ExtractHTTPFields' is unknown or zero
    [C++ Error] Httpapp.hpp(984): E2188 Expression syntax
    [C++ Error] Httpapp.hpp(984): E2293 ) expected
    [C++ Warning] Unit1.cpp(96): W8004 'NodeList' is assigned a value that is never used
    [C++ Error] Unit1.cpp(183): E2096 Illegal structure operation
    [C++ Error] Unit1.cpp(319): E2096 Illegal structure operation
    [C++ Error] Unit1.cpp(473): E2096 Illegal structure operation
    [C++ Error] Unit1.cpp(584): E2096 Illegal structure operation



  • Die erste Fehlermeldung wird durch eine fehlende lib verursacht.
    Versuche doch mal Indy9 statt 10 zu verwenden. Soweit ich weiß funktioniert Indy10 nicht richtig.
    Ich spreche hier aber nicht aus Erfahrung, da ich die Indy-Bibliotheken noch nie verwendet habe.


Anmelden zum Antworten