XPath: 匹配整个单词(使用带有不区分大小写标志的 matches 函数)

7

使用XPath,我想要实现“整字匹配”(就像在VS搜索中一样的选项)。

似乎函数containsmatches的工作方式相似,但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"的结果:

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

如何调整匹配查询以匹配整个单词?

编辑: 我忘了提到我仍然需要使用matches函数,因为我需要不区分大小写的标志。

5个回答

6

使用^$字符作为锚点,如何呢?

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

来自XQuery 1.0和XPath 2.0中的正则表达式语法

添加了两个元字符^$。默认情况下,元字符^匹配整个字符串的开头,而$匹配整个字符串的结尾。


嗯..这给了我想要的结果。但是你能解释一下^$锚点吗?我以前从未使用过它们.. - developer
在答案中添加了一个链接,请参见“两个元字符…”部分。 - Petr Janeček
1
谢谢,我还需要进行一些测试,但这似乎解决了问题! - developer
^$匹配行的开头/结尾,而不是单词边界的开头/结尾。 - neaumusic

4
这里涉及到三个相关的函数/操作符。
matches() 进行正则表达式匹配;你可以使用它来匹配子字符串或通过锚点(^cat$)匹配整个字符串,还可以设置“i”标志使其不区分大小写。
contains() 对子字符串进行精确匹配;你可以使用第三个参数(排序规则)来请求不区分大小写的匹配,但排序规则的指定方式取决于所使用的处理器。
eq 操作符对整个字符串进行精确匹配;可以使用“默认排序规则”(在XPath的情况下通常使用处理器的API进行设置)来请求不区分大小写的匹配。这似乎是最接近您要求的操作符,唯一的缺点是指定排序规则比使用matches()中的“i”标志更依赖于系统。

2
这对你有用吗?
//cat[@*='Cat']

不太是我想要的。我仍然想使用matches函数,因为我需要不区分大小写...(见上面的编辑)。 - developer

2

But I would like to use matches to return results that match "Cat" whole word only:

<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"/>

1

这个:

//cat[@*='Cat']

结果为:

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

我使用 Xacobeo 进行了验证。


不太符合我的要求。我仍然想使用matches函数,因为我需要不区分大小写的匹配(请参见上面的编辑)。 - developer
2
@开发者 试试这个://cat[translate(@*,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='cat']这假设你总是将要匹配的字符串转换为小写。 - Joseph Victor Zammit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接