Я выполняю поиск в XML-файле, используя следующий код:
$result = $xml->xpath("//StopPoint[contains(StopName, '$query')]");
Где $ query – поисковый запрос, а StopName – это имя остановки шины. Проблема в том, что он чувствителен к регистру.
И не только это, я бы также мог искать с неанглийскими персонажами, такими как ÆØÅæøå, чтобы вернуть норвежские имена.
Как это возможно?
В XPath 1.0 (что, я считаю, лучшее, что вы можете получить с помощью PHP SimpleXML), вам нужно будет использовать функцию translate()
для создания вывода из строчного ввода из смешанного ввода.
Для удобства я бы обернул его в такую функцию:
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)"); }
В качестве меры санитарии я либо полностью запретил бы, либо избежал одиночных кавычек в $query
, потому что они сломают вашу строку XPath, если они будут проигнорированы.
В XPath 2.0 вы можете использовать функцию lower-case()
, которая является unicode, поэтому она отлично обрабатывает символы, отличные от ASCII.
contains(lower-case(StopName), lower-case('$query'))
Для доступа к XPath 2.0 вам нужен синтаксический анализатор XSLT 2.0. Например, SAXON . Вы можете получить к нему доступ с PHP через JavaBridge.
Неанглийские имена не должны быть проблемой. Просто добавьте их в свой XPath. (XML определяется как использование Unicode).
Что касается нечувствительности к регистру, …
XPath 1.0 включает следующую инструкцию :
Две строки равны тогда и только тогда, когда они состоят из одной и той же последовательности символов UCS.
Поэтому даже использование явных предикатов для локального имени не поможет.
XPath 2 включает функции для сопоставления фреймов. Например, fn: верхний регистр
Дополнительно: использование функции перевода XPath должно допускать фальсификацию фреймов в XPath 1, но на вход нужно будет указать каждую кодовую точку кода, которую вам и вашим пользователям когда-либо понадобится:
"test" = translate($inputString, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
К тому же:
$ xml-> xpath ("// StopPoint [содержит (StopName, '$ query')]");
Вам нужно будет вычеркнуть любые символы апострофа из запроса $, чтобы не нарушать ваше выражение.
В XPath 2.0 вы можете удвоить цитату, используемую в разделителе, чтобы поместить эту цитату в строковый литерал, но в XPath 1.0 невозможно включить разделитель в строку.