2010-04-13 12 views
7

Dirijo un foro diseñado para apoyar a un grupo internacional de matemáticas. Recientemente lo cambié a unicode para un mejor soporte de caracteres internacionales. Al depurar esta conversión, descubrí que no todos los caracteres Unicode se consideran XHTML válidos (el sitio web pertinente parece ser http://www.w3.org/TR/unicode-xml/). Uno de los pasos que debe seguir el software del foro antes de presentar las publicaciones en el navegador es un paso de validación/desinfección de XHTML. Parece una idea razonable que, en ese momento, elimine cualquier carácter Unicode que no le guste a XHTML.¿Qué debo hacer para eliminar los caracteres Unicode que XHTML considera no válidos con php?

Así que mi pregunta es:

¿Existe una norma (o mejor) manera de hacer esto en PHP?

(El foro está escrito en PHP, por cierto.)

supongo que la prueba de fallos sería un simple str_replace (si eso es también el mejor, qué tengo que hacer nada extra para asegurarse funciona correctamente con unicode?) pero eso implicaría tener que pasar por la DTD XHTML (o la página W3 mencionada anteriormente) con cuidado para averiguar qué caracteres enumerar en la búsqueda parte de str_replace, así que si este es el mejor manera, ¿alguien ya lo hizo para poder robar, errar, copiar?

(Por cierto, el personaje que causó el problema era U + 000C, el 'avance de página', que (según la página W3) es HTML válido pero XHTML válido!)

Respuesta

2

me encontré con una función que podría hacer lo que desee en phpedit.net.

Voy a publicar la función para el archivo, los créditos a LTP en PHPEdit.net:

/** 
* Removes invalid XML 
* 
* @access public 
* @param string $value 
* @return string 
*/ 
function stripInvalidXml($value) 
{ 
    $ret = ""; 
    $current; 
    if (empty($value)) 
    { 
     return $ret; 
    } 

    $length = strlen($value); 
    for ($i=0; $i < $length; $i++) 
    { 
     $current = ord($value{$i}); 
     if (($current == 0x9) || 
      ($current == 0xA) || 
      ($current == 0xD) || 
      (($current >= 0x20) && ($current <= 0xD7FF)) || 
      (($current >= 0xE000) && ($current <= 0xFFFD)) || 
      (($current >= 0x10000) && ($current <= 0x10FFFF))) 
     { 
      $ret .= chr($current); 
     } 
     else 
     { 
      $ret .= " "; 
     } 
    } 
    return $ret; 
} 
+0

Supongo que esto es más rápido que el método preg_replace (especialmente dado el comentario sobre la velocidad en http://php.net/manual/en/regexp.reference.unicode.php), pero tiene el mismo inconveniente que tengo que descubrir mi propia lista blanca. (¡Vea el comentario anterior acerca de ser flojo!) –

+0

No tiene que averiguar su propia lista blanca. Los caracteres están permitidos según el código ASCII y se reemplazan con un espacio cuando quedan fuera del rango especificado por la función. Estoy bastante seguro de que esto es todo lo que necesitarás, la lista blanca ya está en la función. – Bas

+0

Ciertamente hay un * * lista blanca en esa función, pero ¿cómo sé que es correcta la lista blanca? Por ejemplo, 0xC está permitido en HTML pero no en XHTML. Si estoy trabajando desde una lista blanca, debería ser generado de alguna manera desde la DTD. –

1

Asumiendo que su entrada es UTF-8, que puede eliminar rangos Unicode con algo como

preg_replace('~[\x{17A3}-\x{17D3}]~u', '', $input); 

Otro, y mejor enfoque consiste en eliminar todo por defecto y sólo caracteres de lista blanca que desea ver. Las propiedades Unicode (\ p) son bastante prácticas para esto. Por ejemplo, elimina todo excepto letras y números (Unicode):

preg_replace('~[^\p{L}\p{N}]~u', '', $input) 
+0

Mi problema con cualquiera de estos enfoques es que tengo que pasar por el DTD para extraer la lista blanca o negra para contrastar. ¡Tenía la esperanza de que alguien ya lo hubiera hecho por mí! No creo que haya un '\ p {XHTML}' para todos los personajes que son XHTML válidos, ¿verdad? (Soy matemático y fundamentalmente somos un grupo perezoso; si alguien más ya ha resuelto el problema, ¡no queremos molestarnos en hacerlo de nuevo!) –

+0

tampoco conozco esa solución, pero si estás buscando una manera rápida y fácil, simplemente puedes convertir todo excepto letras-números-puntuación en entidades numéricas. – user187291

+0

Convertir "todo-excepto" a entidades no funciona. Si envío un personaje fuera del conjunto válido, incluso cuando está codificado como una entidad, el navegador se quejará. (Tal vez debería aclarar que estoy sirviendo XHTML + MathML para que * * sea 100% válido; no puedo confiar en que el navegador ignore una entidad no válida.) –

Cuestiones relacionadas