组合 XPath 和搜索查询

Combining XPath and Search Queries

要求:

cts/search 查询与 XPath 查询相结合。 XPath 是未知的用户输入字符串。

search:resolve 函数需要 "A cts:query object, a serialized cts:query, or a structured query (search:query)." (Source)

问题:

是否有 api 将 XPath 转换为 cts 或结构化查询,以便我可以将 XPath 和其他搜索查询结合起来?

无效示例:

xquery version "1.0-ml";
let $doc := 
  <test>
    <name>Mike</name>
    <age>20</age>
  </test>
return xdmp:document-insert('mike.xml', $doc);

import module namespace search = "http://marklogic.com/appservices/search"
    at "/MarkLogic/appservices/search/search.xqy";

let $xpath := '/test[name="Mike"]'
let $cts-query := cts:and-query(
   xpathToCts($xpath), (: Somehow convert XPath to cts query here :)
   cts:element-value-query(xs:QName("age"), "20")
)

return search:resolve($cts-query)

如果目前无法将 XPath 字符串转换为 search 兼容格式,是否有任何其他方法可以组合 XPath 和 cts/search 查询?

如有任何帮助,我们将不胜感激!

更新 1:

我尝试使用建议的 searchable-expression 选项,但是 运行 将其与 extract-document-data 结合使用时遇到了另一个问题:

import module namespace search = "http://marklogic.com/appservices/search"
    at "/MarkLogic/appservices/search/search.xqy";

search:resolve(
  cts:element-value-query(xs:QName("name"), "Mike"),
  <options xmlns="http://marklogic.com/appservices/search">
    <searchable-expression>/test[age = 20]</searchable-expression>
    <extract-document-data>
      <extract-path>/test/name</extract-path>
    </extract-document-data>
  </options>
)

此查询 return 提取了以下数据:

<search:extracted-none>
</search:extracted-none>

虽然没有可搜索的表达式,但我得到了预期的结果:

<search:extracted kind="element">
   <name>Mike</name>
</search:extracted>

如果我没记错的话,searchable-expression 的行为与 cts:search 的第一个参数相同。阅读它说的文档:

For example, if you specify //p, then p elements that match the search criteria are returned.

因此,结果节点仅限于可搜索表达式及其下方的所有节点,这不是我想要的。

您可以将该 XPath 传递到 <search:options> 中的 <searchable-expression> 元素,它实际上将是 AND-ed 和您的 cts:query。在幕后,所有 XPath 表达式都被转换为优化的查询计划,就像 cts:queries 一样(除了 XPath 表达式将始终被过滤以防止返回误报,而过滤对于 cts 表达式是可选的) .

但我应该指出,评估用户 XPath 是极其危险的,未经检查是注入攻击的一个巨大漏洞。您应该验证或清理查询以防止这种情况 and/or 确保查询不能 运行 更新,即:/x/y/z[xdmp:directory-delete('/')]。查询顶部的类似内容是一个好的开始:declare option xdmp:update "false";