LWChris: Dezimal codierte Strings decodieren

Hallo,

ich verwende JS um mit einer API zu kommunizieren. Diese gibt mir jedoch dezimal codierte Strings zurück, also z. B. It's statt It's. Gibt es in JavaScript eine Methode, mit der man das decodieren kann, oder muss ich mir selbst eine schreiben?

decodeURIComponent (was die "mächtigste" Decodierfunktion ist die ich bisher kenne decodiert ja nur %HEX codierte Strings).

Wenn ich mir selbst eine schreiben muss, gibt es einen eleganteren Weg als

decodeURIComponent(String.replace(/&#(.*);/g,DecToHex(\1)));

(DecToHex wär dann eine von mir geschriebene Funktion) und geht das so in einem Schritt überhaupt?

Danke, Chris

  1. decodeURIComponent(String.replace(/&#(.*);/g,DecToHex(\1)));

    (DecToHex wär dann eine von mir geschriebene Funktion)

    Warum eine funktion?

    parseInt(10, 10).toString(16);

    und geht das so in einem Schritt überhaupt?

    Ja. http://ejohn.org/blog/search-and-dont-replace/

    1. parseInt(10, 10).toString(16);

      http://ejohn.org/blog/search-and-dont-replace/

      Hey,

      danke für diese beiden Tipps! Es klappt:

      var STRING="It's Goin' Down";  
        
      var STRING2=decodeURIComponent(STRING.replace(/&#(\d+);/g,function(m,Dec){return "%"+parseInt(Dec, 10).toString(16)}));  
        
      // STRING2 => "It's Goin' Down"
      

      Danke nochmal!

      Chris =)

      1. Hi,

        var STRING="It's Goin' Down";

        Dann füg doch mal ein Euro in Deinen String ein:

        var STRING="It's Goin' Down €";

        var STRING2=decodeURIComponent(STRING.replace(/&#(\d+);/g,function(m,Dec){return "%"+parseInt(Dec, 10).toString(16)}));

        und laß Dir das Ergebnis anzeigen.
        Dann siehst Du, daß das so nicht funktioniert (bzw. höchstens, wenn der dezimale Wert kleiner als 256 ist.

        Warum willst Du überhaupt von numerischen Zeichenreferenzen erst auf (fehlerhafte) URL-Codierung gehen, nur um dann die URL-Codierung wieder zu dekodieren?

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        O o ostern ...
        Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
    2. @@suit:

      nuqneH

      Es gibt die Methode String.[ref:self812;javascript/objekte/string.htm#from_char_code@title=fromCharCode](), die das Zeichen zu einen Codepoint (den man aus einer NCR erhält) liefert.

      Warum eine funktion?

      Darum:

      String.prototype.unescape = function ()  
      {  
        return this.replace(/&#([0-9]+);/g, function (m, u) { return String.fromCharCode(parseInt(u, 10)); });  
      };
      
      var s = "It's Goin' Down";  
      s = s.unescape();  
      alert(s);
      

      Das lässt sich auch auf hexadezimale NCRs erweitern:

      String.prototype.unescape = function ()  
      {  
        return this.replace(/&#x([0-9a-f]+);/gi, function (m, u) { return String.fromCharCode(parseInt(u, 16)); }).replace(/&#([0-9]+);/g, function (m, u) { return String.fromCharCode(parseInt(u, 10)); });  
      };
      

      Etwas unschön daran, dass man zweimal mit einem regulären Ausdruck drüber muss.

      Qapla'

      --
      Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
      (Mark Twain)
      1. @@Gunnar Bittersmann:

        nuqneH

        Etwas unschön daran, dass man zweimal mit einem regulären Ausdruck drüber muss.

        Hehe, muss man gar nicht:

        String.prototype.unescape = function ()  
        {  
          return this.replace(/&#([0-9]+|x[0-9a-f]+);/gi, function (m, u) { return String.fromCharCode(u.charAt(0) == 'x' ? parseInt(u.substr(1), 16) : parseInt(u, 10)); });  
        };
        

        Qapla'

        --
        Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
        (Mark Twain)
        1. Hi,

          String.prototype.unescape = function ()

          {
            return this.replace(/&#([0-9]+|x[0-9a-f]+);/gi, function (m, u) { return String.fromCharCode(u.charAt(0) == 'x' ? parseInt(u.substr(1), 16) : parseInt(u, 10)); });
          };

            
          In u scheint der Inhalt der Klammer übergeben zu werden?  
            
          Was passiert, wenn es mehrere Klammern gibt?  
            
          Also so:  
            
          return this.replace(/&#([0-9]+)|x([0-9a-f]+);/gi, function ...  
            
          Ist u dann ein Array? Oder gibt es einen 3. Parameter?  
            
          Dann könnte man ggf. noch auf den substr verzichten, müßte dann halt die Unterscheidung anhand der Länge des ersten/zweiten Klammerinhalts (der ja nur dann leer bzw. null bzw. undefined sein kann, wenn der jeweils andere Zweig matcht) ...  
            
            
          cu,  
          Andreas
          
          -- 
          [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
          [O o ostern ...](http://ostereier.andreas-waechter.de/)  
            
          Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
          
          
          1. @@MudGuard:

            nuqneH

            In u scheint der Inhalt der Klammer übergeben zu werden?

            Ja.

            Was passiert, wenn es mehrere Klammern gibt?
            Also so:
            return this.replace(/&#([0-9]+)|x([0-9a-f]+);/gi, function ...

            Nicht ganz. /&#([0-9]+);|&#x([0-9a-f]+);/gi oder /&#(?:([0-9]+)|x([0-9a-f]+));/gi

            Ist u dann ein Array? Oder gibt es einen 3. Parameter?

            Letzteres, wie im von suit verlinkten http://ejohn.org/blog/search-and-dont-replace/ zu lesen ist.

            Ich war mir nicht sicher, ob veroderte Klammerausdrücker dann verschiedene Parameter oder denselben befüllen. Ersteres ist der Fall.

            Dann könnte man ggf. noch auf den substr verzichten, müßte dann halt die Unterscheidung anhand der Länge des ersten/zweiten Klammerinhalts (der ja nur dann leer bzw. null bzw. undefined sein kann, wenn der jeweils andere Zweig matcht) ...

            Ja.

            String.prototype.unescape = function ()  
            {  
              return this.replace(/&#(?:([0-9]+)|x([0-9a-f]+));/gi, function (m, d, h) { return String.fromCharCode(d ? parseInt(d, 10) : parseInt(h, 16)); });  
            };
            

            Qapla'

            --
            Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
            (Mark Twain)
            1. Hi,

              Nicht ganz. /&#([0-9]+);|&#x([0-9a-f]+);/gi oder /&#(?:([0-9]+)|x([0-9a-f]+));/gi

              Ging eher ums Prinzip als um Perfektion, denn sonst wäre ja nur
              /&#(?:x([0-9a-f]+)|([0-9]+));/gi
              in Frage gekommen - was zu weniger Backtracking führt, wenn die erste Variante nicht zutrifft (das kann bereits nach einem Zeichen festgestellt werden) und wenn ich das richtig sehe, auch dann, wenn  das abschließende ; fehlt).

              Ich war mir nicht sicher, ob veroderte Klammerausdrücker dann verschiedene Parameter oder denselben befüllen. Ersteres ist der Fall.

              Das ist das übliche, die Numerierung (und hier dann die Zuordnung zum Parameter Nummer x) erfolgt ohne Berücksichtigung der Tatsache, ob die capturing Klammer am aktuellen Match beteiligt ist oder nicht, im Regex anhand der öffnenden Klammern von links nach rechts.

              Auch bei ^(a+)?(b+)$ werden die bs auch dann im zweiten capture-Parameter stehen, egal ob as vorhanden sind oder nicht.

              (in Java java.util.regex.Matcher wären die bs in group(2), die as in group(1) - group(0) ist der gesamte Match; in Perl die as in $1, die bs in $2, ist also ziemlich sprachunabhängig)

              cu,
              Andreas

              --
              Warum nennt sich Andreas hier MudGuard?
              O o ostern ...
              Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
              1. @@MudGuard:

                nuqneH

                Ging eher ums Prinzip als um Perfektion,

                Dein Ausdruck matchte auch "xF00;" ohne "&#" vorneweg, das ist von Perfektion ein gutes Stück entfernt. ;-)

                denn sonst wäre ja nur
                /&#(?:x([0-9a-f]+)|([0-9]+));/gi
                in Frage gekommen

                Na wenn du’s sagst, dann drehen wir den Spieß eben um:

                String.prototype.unescape = function ()  
                {  
                  return this.replace(/&#(?:x([0-9a-f]+)|([0-9]+));/gi, function (m, h, d) { return String.fromCharCode(h ? parseInt(h, 16) : parseInt(d, 10)); });  
                };
                

                Das dürfte der Perfektion jetzt aber nahekommen, oder?

                Qapla'

                --
                Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
                (Mark Twain)
                1. Hi,

                  String.prototype.unescape = function ()

                  {
                    return this.replace(/&#(?:x([0-9a-f]+)|([0-9]+));/gi, function (m, h, d) { return String.fromCharCode(h ? parseInt(h, 16) : parseInt(d, 10)); });
                  };

                    
                  
                  > Das dürfte der Perfektion jetzt aber nahekommen, oder?  
                    
                  Hm. Ich weiß nicht.  
                    
                  Ist   statt   erlaubt?  
                  Wenn nein: den i-Modifier weg, dafür aber A-F in die erste [] rein ...  
                    
                  cu,  
                  Andreas
                  
                  -- 
                  [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
                  [O o ostern ...](http://ostereier.andreas-waechter.de/)  
                    
                  Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
                  
                  
                  1. @@MudGuard:

                    nuqneH

                    Ist   statt   erlaubt?

                    In XML nicht. [XML §4.1]

                    Bei SGML bin ich übefragt. Die HTML-Spec sagt: „Die Syntax »&#xH;«, wobei »&#xH;« eine Hexaezimalzahl ist, weist auf die hexadezimale Zeichennummer H in ISO 10646. Hexadezimale Zahlen in numerischen Zeichenreferenzen unterscheiden nicht zwischen Groß- und Kleinschreibung.“ [HTML401 §5.3.1]

                    Von einem großen X ist keine Rede. Browser schlucken’s (bei 'text/html') trotzdem. Sollte das Script sein Verhalten dem von Tagsoup-Parsern anpassen oder streng standardkonform arbeiten?

                    Qapla'

                    --
                    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
                    (Mark Twain)
        2. @@Gunnar Bittersmann:

          nuqneH

          String.prototype.unescape = function ()

          {
            return this.replace(/&#([0-9]+|x[0-9a-f]+);/gi, function (m, u) { return String.fromCharCode(u.charAt(0) == 'x' ? parseInt(u.substr(1), 16) : parseInt(u, 10)); });
          };

            
          Wobei sich hier [MudGuards Einwand](https://forum.selfhtml.org/?t=199684&m=1344264) als Fallstrick erweist:  
            
          Der reguläre Audruck matcht auch auf "B", dann wird aber nur kleines 'x' abgefragt und somit parseInt("X42", 10) aufgerufen, was 0 zurückgibt. Ein in den Text eingefügtes U+0000 ist ganz sicher nicht das, was man möchte.  
            
          Qapla'
          
          -- 
          Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.  
          (Mark Twain)
          
  2. Hi,

    ich verwende JS um mit einer API zu kommunizieren. Diese gibt mir jedoch dezimal codierte Strings zurück, also z. B. It's statt It's.

    decodeURIComponent (was die "mächtigste" Decodierfunktion ist die ich bisher kenne decodiert ja nur %HEX codierte Strings).

    Da die Daten nicht URL-codierst sind, ist es natürlich nicht nötig, sie zu URL-decodieren.

    Wenn ich mir selbst eine schreiben muss, gibt es einen eleganteren Weg als
    decodeURIComponent(String.replace(/&#(.*);/g,DecToHex(\1)));

    Damit hättest Du dann statt dezimaler Zeichenreferenzen sedezimale Zeichenreferenzen.
    Was versprichst Du Dir davon?

    Ich wüßte keinen Fall, in dem dezimale Zeichenreferenzen nicht akzeptiert werden, sedezimale aber schon.

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    O o ostern ...
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
    1. Damit hättest Du dann statt dezimaler Zeichenreferenzen sedezimale Zeichenreferenzen.
      Was versprichst Du Dir davon?

      Ich wüßte keinen Fall, in dem dezimale Zeichenreferenzen nicht akzeptiert werden, sedezimale aber schon.

      Ich weiß nicht, ob ich dich richtig verstanden habe, aber vielleicht ist dies die Antwort:

      Von der Umwandlung versprach ich mir, dass ich dann decodeURIComponent einsetzen kann, was auch geklappt hat.

      Ich muss den Text, der von der API zurückkommt, in eine Textarea einfügen, aber eben nicht als "It's Goin' Down", sondern als "It's Goin' Down". Daher war das Decodieren notwendig.

      Danke trotzdem,

      Chris

      1. Hi,

        Ich muss den Text, der von der API zurückkommt, in eine Textarea einfügen, aber eben nicht als "It's Goin' Down", sondern als "It's Goin' Down". Daher war das Decodieren notwendig.

        Kein einziger meiner Testbrowser (Opera, Firefox, Safari, Chrome in aktuellen Versionen, IE im IETester von 8 bis 5.5) hat sich geweigert, das genannte Textliteral textarea.innerHTML zuzuweisen, und alle haben anschließend
        It's Goin' Down
        in der Textarea dargestellt.

        (Test per Eingabe von javascript:... über die Adresszeile.)

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
  3. Ich hab da was probiert:

    <script type="text/javascript">  
    var text="&copy; &#1027;  &#x1027;"  
    alert(text);  
    var x = document.createElement('div');  
    x.innerHTML=text;  
    alert(x.firstChild.data);  
    </script>  
    
    

    Ich verwende die Tatsache, dass innerHTML HTML erwartet.
    ob.data aber einen Textknoten im Encoding des Browsers/Documents darstellt.

    Getestet im FX 3.6

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. [latex]Mae  govannen![/latex]

      Getestet im FX 3.6

      • Opera 10.70
      • IE 7.0.5730.11:
      • Chrome 5.0.375.126 Uncaught Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7

      1.) &copy; &#1027;  &#x1027;
      2.) © Ѓ  ဧ

      Cü,

      Kai

      --
      Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken in Richtung "Mess up the Web". (suit)
      Foren-Stylesheet Site Selfzeug JS-Lookup
      SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?