XPath: Соответствие всему слову (используя функцию сопоставления с флагом без учета регистра)

Используя XPath, я хотел бы «Сопоставить целое слово» (опция для пользователя, как и в поиске VS).

Кажется, что функции contains и matches работают одинаково, хотя совпадения позволяют использовать флаги, такие как i, для нечувствительности к регистру.

Другими словами, я получаю одинаковые результаты с этими двумя запросами XPath:

<pets>
    <dog name="Rupert" color="grey"/>
    <dog name="Ralph" color="brown"/>
    <cat name="Marvin the Cat" color="white"/>
    <cat name="Garfield the Cat" color="orange"/>
    <cat name="Cat" color="grey"/>
    <cat name="Fluffy" color="black"/>
</pets>

Matches XPath: //cat[descendant-or-self::*[@*[matches(.,'Cat')]]]
    returns:
    <cat name="Marvin the Cat" color="white"/>
    <cat name="Garfield the Cat" color="orange"/>
    <cat name="Cat" color="grey"/>


Contains XPath: //cat[descendant-or-self::*[@*[contains(.,'Cat')]]]
    returns:
    <cat name="Marvin the Cat" color="white"/>
    <cat name="Garfield the Cat" color="orange"/>
    <cat name="Cat" color="grey"/>

Но я хотел бы использовать matches для возврата результатов, которые соответствуют только целому слову «Кошка»:

<cat name="Cat" color="grey"/>

Как я могу настроить запрос совпадений, чтобы он соответствовал всему слову?

EDIT: я забыл упомянуть, что мне все еще нужно использовать функцию совпадений, потому что мне нужен флаг нечувствительности к регистру.


person developer    schedule 01.05.2012    source источник


Ответы (5)


Как насчет использования символов ^ и $ в качестве якорей?

//cat[descendant-or-self::*[@*[matches(.,'^Cat$')]]]

Из Синтаксис RegEx в XQuery 1.0 и XPath 2.0:

Добавляются два метасимвола, ^ и $. По умолчанию метасимвол ^ соответствует началу всей строки, а $ соответствует концу всей строки.

person Petr Janeček    schedule 01.05.2012
comment
Хм .. это дает мне результат, который я хочу. Но не могли бы вы объяснить якоря ^$? я никогда раньше им не пользовалась.. - person developer; 02.05.2012
comment
Добавил ссылку в ответ, см. раздел Два метасимвола.... - person Petr Janeček; 02.05.2012
comment
Спасибо, мне все еще нужно будет провести некоторые тесты, но, похоже, это помогает! - person developer; 02.05.2012
comment
^ и $ соответствуют началу/концу строки, а не началу/концу подстрок с границей слова - person neaumusic; 27.03.2020

Здесь есть три релевантных функции/оператора.

matches() выполняет сопоставление с регулярным выражением; вы можете использовать его для сопоставления подстроки или для сопоставления всей строки с помощью якорей (^cat$), и вы можете установить флаг 'i', чтобы сделать его без учета регистра.

contains() выполняет точное совпадение подстроки; вы можете использовать третий аргумент (сопоставление) для запроса совпадения без учета регистра, но способ указания сопоставления зависит от используемого вами процессора.

Оператор eq выполняет точное соответствие всей строки; «сопоставление по умолчанию» (которое в случае XPath обычно устанавливается с помощью API процессора) может использоваться для запроса сопоставления без учета регистра. Кажется, это тот, который ближе всего к вашему требованию, единственный недостаток заключается в том, что указание сопоставления более зависит от системы, чем использование флага «i» с match().

person Michael Kay    schedule 01.05.2012

Будет ли это работать для вас?

//cat[@*='Cat']
person Oliver    schedule 01.05.2012
comment
Не совсем то, что я ищу. Я все еще хочу использовать функцию совпадений, потому что мне нужна нечувствительность к регистру... (см. редактирование выше). - person developer; 02.05.2012

Но я хотел бы использовать совпадения для возврата результатов, которые соответствуют только целому слову «Кошка»:

<cat name="Cat" color="grey"/>

Существуют разные выражения XPath, которые выбирают нужный элемент:

Использовать:

/*/cat[matches(@name, '^cat$', 'i')]

Или используйте:

/*/cat[lower-case(@name) eq 'cat']

Проверка на основе XSLT:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:copy-of select=
   "/*/cat[matches(@name, '^cat$', 'i')]"/>
======
  <xsl:copy-of select=
   "/*/cat[lower-case(@name) eq 'cat']"/>

 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному XML-документу:

<pets>
    <dog name="Rupert" color="grey"/>
    <dog name="Ralph" color="brown"/>
    <cat name="Marvin the Cat" color="white"/>
    <cat name="Garfield the Cat" color="orange"/>
    <cat name="Cat" color="grey"/>
    <cat name="Fluffy" color="black"/>
</pets>

это преобразование оценивает два выражения XPath и копирует выбранные элементы в выходные данные:

  <cat name="Cat" color="grey"/>
======
  <cat name="Cat" color="grey"/>
person Dimitre Novatchev    schedule 02.05.2012

Этот:

//cat[@*='Cat']

приводит к:

<cat name="Cat" color="grey"/>

Я проверил с помощью Xacobeo.

person Joseph Victor Zammit    schedule 01.05.2012
comment
Не совсем то, что я ищу. Я все еще хочу использовать функцию совпадений, потому что мне нужна нечувствительность к регистру... (см. редактирование выше). - person developer; 02.05.2012
comment
@developer Попробуйте это: //cat[translate(@*,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='cat'] Это предполагает, что вы всегда передаете строку, которую хотите сопоставить, в нижнем регистре. - person Joseph Victor Zammit; 02.05.2012