2009-03-09 15 views
7

Estoy realizando una búsqueda en un archivo XML, usando el siguiente código:¿Cómo puedo usar XPath para realizar una búsqueda insensible a mayúsculas y minúsculas y soportar caracteres no ingleses?

$result = $xml->xpath("//StopPoint[contains(StopName, '$query')]"); 

Donde $ consulta es la consulta de búsqueda, y StopName es el nombre de una parada de autobús. El problema es que es sensible a mayúsculas y minúsculas.

Y no solo eso, también podría buscar caracteres no ingleses como ÆØÅæøå para devolver nombres noruegos.

¿Cómo es esto posible?

+0

Para aquellos que buscan una solución a este problema, aquí hay un artículo que analiza un enfoque alternativo: http://codingexplained.com/coding/php/solving-xpath-case-sensitivity-with-php – Andy0708

Respuesta

12

En XPath 1.0 (que es, creo que es lo mejor que se puede obtener con PHP SimpleXML), tendría que usar la función translate() para producir una salida en minúsculas desde la entrada de casos mezclados.

Para mayor comodidad, me envuelve en una función como esta:

function findStopPointByName($xml, $query) { 
    $upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"; // add any characters... 
    $lower = "abcdefghijklmnopqrstuvwxyzæøå"; // ...that are missing 

    $arg_stopname = "translate(StopName, '$upper', '$lower')"; 
    $arg_query = "translate('$query', '$upper', '$lower')"; 

    return $xml->xpath("//StopPoint[contains($arg_stopname, $arg_query)"); 
} 

Como medida de desinfección yo sea completamente prohibir o escapar comillas simples en $query, porque van a romper la cadena de XPath si están ignorado

3

Los nombres que no están en inglés no deberían ser un problema. Solo agrégalos a tu XPath. (XML se define como usar Unicode).

Como para el caso-insensibilidad, ...

XPath 1.0 incluye la siguiente statement:

dos cadenas son iguales si y sólo si consisten en la misma secuencia de caracteres UCS.

De modo que incluso usar predicados explícitos en el nombre local no ayudará.

XPath 2 incluye funciones para asignar el caso. P.ej. fn:upper-case


adicional: el uso de XPath función translate debe permitir la asignación de casos a ser falsificada en XPath 1, pero la entrada tendrá que incluir todos los puntos de código entubado usted y sus usuarios necesitará siempre:

"test" = translate($inputString, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ") 
+0

Gracias. Mi archivo XML no fue unicoded –

+0

Como comenté a continuación, PHP me dice que la función minúsculas y mayúsculas no se puede encontrar ..:/ –

+0

@termserv: XML es * siempre * unicode. Incluso si sus archivos XML no están en una codificación con capacidad Unicode, una vez en la memoria esto no cambiará nada. – Richard

9

En XPath 2.0 puede usar la función lower-case(), que es compatible con Unicode, por lo que manejará bien caracteres que no sean ASCII.

contains(lower-case(StopName), lower-case('$query')) 

Para acceder a XPath 2.0 necesita el analizador XSLT 2.0. Por ejemplo SAXON. Puede acceder al from PHP a través de JavaBridge.

+0

Esto me da los siguientes errores: - xmlXPathCompOpEval : función minúscula no encontrada - Función no registrada –

+0

Probablemente esté usando XPath 1.0, esta función solo está disponible en XPath 2.0 – vartec

+0

Lo resolví con el uso de translate, para convertir todos los caracteres a minúsculas. Gracias por su ayuda :) –

0

Además:

$ xml-> XPath ("// StopPoint [contiene (StopName, '$ consulta')]");

Deberá quitar los caracteres de apóstrofo de $ consulta para evitar romper su expresión.

En XPath 2.0 puede duplicar la cita que se utiliza en el delimitador para poner esa cita en una cadena literal, pero en XPath 1.0 es imposible incluir el delimitador en la cadena.

Cuestiones relacionadas