根据特定单词的计数进行搜索

时间:2013-05-21 12:46:50

标签: xml xquery

以下是XML文件示例。

<Docs>
 <Doc>
  <Name>Doc 1</Name>
  <Info>Hurray</Info>
 </Doc>
 <Doc>
  <Name>Doc 2</Name>
  <Info>Brinjal is king of vegetables.</Info>
 </Doc>
 <Doc>
  <Name>Doc 3</Name>
  <Info>Alexandar was a great king. His desire was to conquer the world and rule the  world as a king.</Info>
 </Doc>
 <Doc>
  <Name>Doc 4</Name>
  <Info>I love cherries.</Info>
 </Doc>
 <Doc>
  <Name>Doc 5</Name>
  <Info>Mango is king of fruits. Alphonso is king of mangoes. So Alphonso is king's king.</Info>
 </Doc>
</Docs>

我想在标签中搜索单词“king”并返回as输出。我知道这很简单...... :)

但是顺序应该是搜索到的单词的顺序(这里它将是王),即大多数数字将首先出现。

Doc 5(3次王) Doc 3(2次国王) Doc 2(1次王)

3 个答案:

答案 0 :(得分:1)

正如您之前在BaseX邮件列表中提出的问题,我假设您使用的是BaseX作为处理器。假设$doc保存提供的xml输入,以下显示了所需的结果:

for $e in $doc//Doc
let $copy := copy $c := $e/Info modify () return $c
let $count := ft:count($copy[. contains text 'King'])
order by $count descending
where $count > 0
return <Result>{$e/Name}<count>{$count}</count></Result>

这里有两件特别的事情:

  • $copy语句是一个简单的副本,是必需的,因为ft:count期望数据库节点作为输入。如果您的片段已经在数据库中,则不需要此。
  • ft:count是特定于供应商的BaseX,不幸的是它不是全文规范的一部分。

答案 1 :(得分:1)

使用order by

let $token := 'king'
for $doc in //Doc
let $count := count(tokenize($doc/Info, "[\W]")[lower-case(.) = lower-case($token)])
where $count > 0
order by $count descending
return concat($doc/Name, " (", $count, " time", "s"[$count>1], " ", $token, ")")

此表达式拆分非单词字符\W。根据您的应用程序,您可能希望使用另一个正则表达式进行标记化。

答案 2 :(得分:0)

获得所需输出的另一个例子是:

for $Doc in doc("file:/C:/Users/vgv/Desktop/Testing/Untitled1.xml")//Doc
let $DocName := $Doc/Name/text()
let $KingCount := count(tokenize($Doc/Info,'king'))
order by $KingCount descending
return
concat($DocName, ' (', $KingCount, ' times king)')