【问题标题】:Xquery ( XDMP-ARGTYPE error ) the expected type of a function input is different from the actual typeXquery ( XDMP-ARGTYPE 错误 ) 函数输入的预期类型与实际类型不同
【发布时间】:2016-06-25 21:48:20
【问题描述】:

我正在尝试使用此功能从 MarkLogic 8 中的文本中删除停用词:

declare function rec:remove-stop-words($string, $stop_words)  {  
  (: This is a recursive function. :)  
  if(not(empty($stop_words))) then  
    rec:remove-stop-words(  
      replace($string, $stop_words[1], '', 'i'),  
      (: This passes along the stop words after 
         the one just evaluated. :)  
      $stop_words[position() > 1]  
    )  
  else normalize-space($string)  
};  

这里我叫它

for $r in /rec:Record
return
  rec:remove-stop-words(data($r/rec:Abstract), $stop_words}

它给了我以下错误

XDMP-ARGTYPE: (err:XPTY0004) fn:replace((xs:untypedAtomic(" 章节 利用 n..."), xs:untypedAtomic(" 书 ..."))、"a"、""、"i") 之间的相互关系 -- arg1 不是 xs:string 类型?

该函数需要string 类型,但实际类型是untypedAtomic。我不知道该怎么办! 注意:((问题不在函数中,因为我尝试将它用于不同的文本并且效果很好))。

我尝试通过以下方式将untypedAtomic 转换为string 代码:

return
  <info>{rec:remove-stop-words(data(xs:string($r/rec:Abstract)), $stop_words)}</info>

但我收到了这个错误:

XDMP-ARGTYPE: (err:XPTY0004) fn:replace((" 章节 利用 n 的不对称性...", " 书 ...")、"a"、""、"i") 之间的相互关系 -- arg1 不是 xs:string 类型

【问题讨论】:

    标签: string xquery marklogic type-conversion untyped-variables


    【解决方案1】:

    问题在于,当您遍历/rec:Record 并将$r/rec:Abstract 作为输入传递时,您的至少一条记录会返回多个rec:Abstractrec:remove-stop-words 的函数签名允许将一系列值作为 $string 的输入,但调用 fn:replace 的函数体仅处理单个值的输入,因此它会引发参数异常(给定 xs:string+ 并期望xs:string?)。

    您可以在调用函数之前通过迭代rec:Abstract 来处理序列:

    for $r in /rec:Record
    for $a in $r/rec:Abstract
    return
    rec:remove-stop-words($a, $stop_words)
    

    如果您使用更严格的函数签名,它可以帮助避免此类问题,或者至少使它们更易于调试。例如,如果您将函数定义为仅允许对第一个参数进行单个输入:

    rec:remove-stop-words($string as xs:string, $stop_words as xs:string*)
    ...
    

    $string 被传递一个序列时,这将引发类似的异常,但在调用堆栈的更高层,这有助于使这些类型的错误更加明显。

    【讨论】:

    • 更易于阅读,更简洁地调整 XPath 并仅使用一个 FLWOR 来处理 rec:Abstract 元素并获取其计算的 string() 值:for $r in /rec:Record/rec:Abstract/string()
    • @MadsHansen 我一般同意,但 OP 可能有理由迭代另一个节点。人们通常只发布一个 sn-p 或简化示例,有时做出这样的假设会破坏他们的代码,从而导致更多问题。
    【解决方案2】:

    尝试使用此代码 -

    for $r in /rec:Record
    
    return
    rec:remove-stop-words(fn:string($r/rec:Abstract), $stop_words}
    

    【讨论】:

      【解决方案3】:

      看起来你正在向它发送一个节点而不是一个字符串。试试$r/rec:Abstract/text()$r/rec:Abstract/string()

      【讨论】:

      • 我试过了,我得到了这个XDMP-ARGTYPE: (err:XPTY0004) fn:replace(("&amp;#10;&amp;#9;&amp;#9;&amp;#9;", "&amp;#10;&amp;#9;&amp;#9;&amp;#9;", "&amp;#10;&amp;#9;&amp;#9;"), "a", "", "i") -- arg1 is not of type xs:string?
      • 看起来可能有不止一个摘要。试试 $r/rec:Abstract/text()[1]
      • 如果有多个,你可以使用 string-join 使其成为一个
      • 在大多数情况下,最好使用*/string() 而不是*/text(),这样它会为所选元素返回单个字符串,并且如果该元素碰巧有混合内容,它会继续工作。
      • 好点马兹。我只是想看看 abstract 在 for clouse 中是否有多个元素,看起来确实如此。在大多数情况下,我会使用 xs:string。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-15
      • 1970-01-01
      • 2016-07-18
      • 1970-01-01
      相关资源
      最近更新 更多