Estoy usando PHPUnit para validar el resultado XML de mi código PHP, pero aparentemente tengo problemas con la codificación de caracteres MySQL. Aquí está el error que recibo de DOMDocument:¿Cómo hago que MySQL devuelva UTF-8?
Input is not proper UTF-8, indicate encoding!
Bytes: 0xE9 0x20 0x42 0x65
Me inicializar el DOMDocument por lo que utiliza la codificación correcta:
$domDocument = new DOMDocument('1.0','UTF-8');
Y cuando compruebo la salida de saveXML() usando mb_detect_encoding el resultado es UTF-8 .
También comprobé todas las llamadas que se utilizan para crear el XML, usando mb_detect_encoding en todos los parámetros createCDATASection encontradas y todos son UTF-8 o ASCII (no hay nodos de texto sin formato, todo está en CDATA bloques).
Creo que el problema proviene del uso de un carácter 'é' (que es 0xE9 en ISO 8859-1). La línea que añade que el carácter a mi XML es:
$domDocument->createCDATASection($place->name);
y mb_detect_encoding ($ lugar-> nombre) me da UTF-8.
Los datos ($ place-> name) se extraen de una base de datos MySQL. Esta base de datos tiene el juego de caracteres UTF-8.
Aquí es un código de ejemplo:
$query = sprintf('SELECT name FROM place where id = 1');
$result = mysql_query($query);
$result = mysql_fetch_assoc($result);
// -- Feeding UTF-8 data directly WORKS
$domDocument = new DOMDocument('1.0','UTF-8');
$rootNode = $domDocument->createElement('Response');
$rootNode->appendChild($domDocument->createCDATASection('Café Belga'));
$domDocument->appendChild($rootNode);
$matcher = array('tag' => 'Response');
self::assertTag($matcher, $domDocument->saveXML(), '', FALSE);
// -- Feeding UTF-8 data from the resultset FAILS
$domDocument = new DOMDocument('1.0','UTF-8');
$rootNode = $domDocument->createElement('Response');
$rootNode->appendChild($domDocument->createCDATASection($result['name']));
$domDocument->appendChild($rootNode);
$matcher = array('tag' => 'Response');
self::assertTag($matcher, $domDocument->saveXML(), '', FALSE);
En mi depurador PhpStorm, la cadena tomaron de la base de datos es el siguiente:
Café Belga
Así que creo esa es la raíz del problema. En MySQLWorkbench, la cadena es correcta: Café Belga.
¡Cuando se usa utf8_encode($result['name'])
, sin embargo, todo funciona bien!
Una comprobación más en la ventana de relojes:
mb_detect_encoding($result['name'])
-> "UTF-8"
mb_detect_encoding(utf8_encode($result['name']))
-> "UTF-8"
En una nota lateral, ¿Hay algún sitio donde Puedo simplemente copiar y pegar esos valores hexadecimales y ver qué personajes se supone que tienen en diferentes conjuntos de caracteres.
¿Dónde se almacena el carácter 'E'? En un archivo? En tu código? – Yeroon
Vaya, se olvidó de mencionar esto, edité mi pregunta: los datos se extraen de una base de datos mysql. Esta base de datos tiene el conjunto de caracteres utf8. –
@Joris ¿usas loadXml en algún momento después de crear el domdocumento? Además, ¿puede proporcionarnos un modelo de prueba reproducible que ilustre el problema? – Gordon