Как я могу использовать XPath для поиска без учета регистра и поддержки неанглийских символов? - PullRequest
7 голосов
/ 09 марта 2009

Я выполняю поиск в файле XML, используя следующий код:

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

Где $ query - это поисковый запрос, а StopName - это имя автобусной остановки. Проблема в том, что он чувствителен к регистру.

И не только это, я также мог бы искать с неанглийскими символами, такими как toØÅæøå, чтобы вернуть норвежские имена.

Как это возможно?

Ответы [ 4 ]

12 голосов
/ 09 марта 2009

В 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, если их игнорируют.

9 голосов
/ 09 марта 2009

В XPath 2.0 вы можете использовать функцию lower-case(), которая поддерживает Unicode, поэтому она будет отлично обрабатывать символы не ASCII.

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

Для доступа к XPath 2.0 вам понадобится парсер XSLT 2.0. Например SAXON . Вы можете получить к нему доступ из PHP через JavaBridge.

3 голосов
/ 09 марта 2009

Неанглийские имена не должны быть проблемой. Просто добавьте их в свой XPath. (XML определяется как использующий Unicode).

Что касается нечувствительности к регистру, ...

XPath 1.0 включает следующую инструкцию :

Две строки равны тогда и только тогда, когда они состоят из одинаковой последовательности символов UCS.

Так что даже использование явных предикатов для локального имени не поможет.

XPath 2 включает функции для отображения случая. Например. п: прописные


Дополнительно: использование функции перевода XPath должно позволить подделывать сопоставление регистра в XPath 1, но ввод должен включать каждый кодированный код, который вам и вашим пользователям когда-либо потребуется:

"test" = translate($inputString, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
0 голосов
/ 09 марта 2009

Дополнительно:

$ xml-> xpath ("// StopPoint [содержит (StopName, '$ query')]");

Вам нужно будет удалить любые символы апострофа из $ query, чтобы избежать нарушения выражения.

В XPath 2.0 вы можете удвоить кавычку, используемую в разделителе, чтобы поместить эту кавычку в строковый литерал, но в XPath 1.0 невозможно включить разделитель в строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...