2009-03-09 9 views
7

sto eseguendo una ricerca in un file XML, utilizzando il seguente codice:Come posso utilizzare XPath per eseguire una ricerca senza distinzione tra maiuscole e minuscole e supportare caratteri non inglesi?

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

Dove $ query è la query di ricerca, e StopName è il nome di una fermata dell'autobus. Il problema è che è case sensitive.

E non solo, sarei anche in grado di cercare con caratteri non inglesi come ÆØÅæøå per restituire nomi norvegesi.

Com'è possibile?

+0

Per coloro che cercano una soluzione a questo problema, ecco un articolo che illustra un approccio alternativo: http://codingexplained.com/coding/php/solving-xpath-case-sensitivity-with-php – Andy0708

risposta

12

In XPath 1.0 (che è, credo, il meglio che si può ottenere con PHP SimpleXML), si dovrebbe usare la funzione translate() per produrre output tutto in minuscolo da input maiuscole.

Per comodità, vorrei avvolgerlo in una funzione come questa:

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)"); 
} 

Come misura di sanificazione avrei o completamente vietare o fuggire apici in $query, perché si rompono la stringa XPath se sono ignorato.

3

I nomi non inglesi non dovrebbero essere un problema. Basta aggiungerli al tuo XPath. (XML è definito come utilizzando Unicode).

Come per il caso-insensibilità, ...

XPath 1.0 include quanto segue statement:

due stringhe sono uguali se e solo se consistono nella stessa sequenza di caratteri UCS.

Quindi anche l'utilizzo di predicati espliciti sul nome locale non aiuta.

XPath 2 include funzioni per mappare il caso. Per esempio. fn:upper-case


aggiuntive: usando XPath di funzione translate dovrebbe consentire caso mappatura essere falsificato in XPath 1, ma l'ingresso dovrà includere ogni punto di codice con carter voi ei vostri utenti avrà mai bisogno:

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

Grazie. Il mio file XML non era unicode. –

+0

Come ho commentato qui sotto, PHP mi dice che la funzione minuscola e maiuscola non può essere trovata ..:/ –

+0

@termserv: XML è * sempre * unicode. Anche se i tuoi file XML non sono in una codifica compatibile con Unicode, una volta in memoria non farà alcuna differenza. – Richard

9

In XPath 2.0 è possibile utilizzare la funzione lower-case(), che è sensibile all'unicode, quindi gestirà i caratteri non ASCII.

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

Per accedere a XPath 2.0 è necessario il parser XSLT 2.0. Ad esempio SAXON. È possibile accedervi from PHP tramite JavaBridge.

+0

Questo mi dà i seguenti errori: - xmlXPathCompOpEval : funzione minuscola non trovata - Funzione non registrata –

+0

Probabilmente stai usando XPath 1.0, questa funzione è disponibile solo in XPath 2.0 – vartec

+0

Ho risolto il problema con l'uso di translate, per convertire tutti i caratteri in minuscolo. Grazie per il vostro aiuto :) –

0

Inoltre:

$ XML> XPath ("// StopPoint [contiene (StopName, '$ query')]");

Sarà necessario rimuovere tutti i caratteri di apostrofo da $ query per evitare di rompere la tua espressione.

In XPath 2.0 puoi raddoppiare la quota usata nel delimitatore per mettere quella citazione in una stringa letterale, ma in XPath 1.0 è impossibile includere il delimitatore nella stringa.

Problemi correlati