Dezimal codierte Strings decodieren
LWChris
- javascript
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
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?
parseInt(10, 10).toString(16);
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 =)
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
@@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'
@@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'
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.
@@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'
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
@@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'
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.
@@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'
@@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)
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
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
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
Ich hab da was probiert:
<script type="text/javascript">
var text="© Ѓ ဧ"
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
[latex]Mae govannen![/latex]
Getestet im FX 3.6
1.) © Ѓ ဧ
2.) © Ѓ ဧ
Cü,
Kai