molily: Interpunktionszeichen in UTF-8 convertieren

Beitrag lesen

Hallo,

$string = '<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
ö ´–
</body>
</html>';

echo uft_encode($string);
// bzw:
echo iconv('ISO-8859-1', 'UTF-8', $string);

  
Das ist widersinnig. Du sagst iconv, dass das Dokument in ISO-8859-1 kodiert ist, weißt aber genau, dass es Zeichen enthält, die nicht mit ISO-8859-1 kodierbar sind? Äh? Was steht denn dann genau im Dokument?  
  
Meiner Vermutung nach ist es gar nicht in ISO-8859-1 kodiert, sondern in Windows-1252. Dort gibt es das Zeichen – (U+2013), es wird mit 0x96 kodiert. Schau dir mal das Dokument bzw. das PHP-Script in einem Hexeditor an. Wenn du ein Byte 0x96 findest, ist es wohl Windows-1252-kodiert. In ISO-8859-1 steht an der Stelle ein Steuerzeichen.  
  
In dem Fall müsstest du korrekt iconv('Windows-1252', 'UTF-8', $string) notieren. Ein kleiner Test:  
  
~~~php
<?php  
function list_bytes ($str) {  
 $i = 0;  
 while (isset($str{$i})) {  
  echo(($io = ord($str{$i})) . ' | 0x' . dechex($io) . "\n");  
  $i++;  
 }  
 echo("\n");  
}  
  
list_bytes(iconv('ISO-8859-1', 'UTF-8', "\x96"));  
list_bytes(iconv('Windows-1252', 'UTF-8', "\x96"));  
?>

Ausgabe:
194 | 0xc2
150 | 0x96

226 | 0xe2
128 | 0x80
147 | 0x93

Die erste Bytesequenz ist die UTF-8-Kodierung des Zeichens U+0096. Dies ist wie gesagt ein nicht druckbares Steuerzeichen (welches im übrigen in HTML und XHTML nicht vorkommen darf, wenn ich mich recht entsinne).
Die zweite Bytesequenz ist die UTF-8-Kodierung des gewünschten Zeichens U+2013.

Mathias