1

我之前问这个的尝试显然太复杂了,再试一次!我正在 Xquery 中进行搜索。在其中一个字段(标题)中应该可以输入多个关键字。目前只有一个关键字有效。当有多个时,会出现错误ERROR XPTY0004: The actual cardinality for parameter 1 does not match the cardinality 在函数签名中声明: concat($atomizable-values as xs:anyAtomicType?, ...) xs:string? . 预期基数:0 或 1,得到 2。

在我的 xquery 中,我试图通过 \s 标记关键字,然后单独匹配它们。我认为这种方法可能是错误的,但我不确定要使用什么其他方法。我明明是初学者!!

这是要搜索的示例 XML:

<files>

<file>
<identifier>
    <institution>name1</institution>
    <idno>signature</idno>
</identifier>
<title>Math is fun</title>
</file>

<file>
<identifier>
    <institution>name1</institution>
    <idno>signature1</idno>
</identifier>
<title>philosophy of math</title>
</file>

<file>
<identifier>
    <institution>name2</institution>
    <idno>signature2</idno>
</identifier>
<title>i like cupcakes</title>
</file>

</files>

这是 Xquery,其中搜索字段标题为示例输入“math”,搜索字段机构为“name1”。这行得通,搜索输出是标题“数学很有趣”和“数学哲学”。如果您将输入 ($title) 更改为“数学乐趣”,则不起作用。然后您会收到错误消息。所需的输出是标题“数学很有趣”。

xquery version "3.0";

let $institution := 'name1'
let $title := 'math' (:change to 'math fun' and doesn't work anymore, only a single word works:)


let $title-predicate := 
if ($title)
 then
    if (contains($title, '"'))
    then concat("[contains(lower-case(title), '", replace($title, '["]', ''), "')]")  (:This works fine:)
    else
    for $title2 in tokenize($title, '\s') (:HERE IS THE PROBLEM, this only works when the input is a single word, for instance 'math' not 'math fun':)
    return
    concat("[matches(lower-case(title), '", $title2, "')]")
else ()


let $institution-predicate := if ($institution) then concat('[lower-case(string-join(identifier/institution))', " = '", $institution, "']") else ()


let $eval-string := concat
("doc('/db/Unbenannt.xml')//file", 
$institution-predicate,
$title-predicate
)


let $records := util:eval($eval-string) 
let $test := count($records)
let $content :=

                        <inner_container>
                            <div>
                                <h2>Search Results</h2>

                              <ul>
                               {
                              for $record in $records
                              return
                                <li id="searchList">  
                                <span>{$record//institution/text()}</span> <br/>
                                <span>{$record//title/text()}</span>
                                </li>
                                }
                              </ul>
                            </div>
                            </inner_container>

return 
$content
4

2 回答 2

1

您必须使用 string-join() 包装您的 FLWOR 表达式:

string-join(
    for $title2 in tokenize($title, '\s')
    return
    concat("[matches(lower-case(title), '", $title2, "')]")
)
于 2016-10-24T12:55:30.187 回答
0

如果tokenize($title)返回一个字符串序列,那么

for $title2 in tokenize($title, '\s')
return concat("[matches(lower-case(title), '", $title2, "')]")

还将返回一个字符串序列

因此$title-predicate将是一个字符串序列,您不能提供一个字符串序列作为concat().

所以很清楚出了什么问题,但修复它需要对您的查询有更深入的了解,而不是我有时间获得。

我很难相信将查询生成为字符串然后对该查询进行动态评估的方法确实是必要的。

于 2016-10-21T22:36:50.693 回答