XQuery concat未按预期方式输出文档XML

XQuery concat未按预期方式输出文档XML,xquery,marklogic,Xquery,Marklogic,返回 let $d := doc('foo.xml') return concat('let $d := 

', $d) 我需要它返回: let $d := bar 读取fn:concat的函数签名,没有理由期望它输出XML。从 也就是说,它接受可变数量的原子项并返回一个字符串。因此,如果您向它传递一个XML节点,它将尝试将其原子化并返回一个字符串结果。如果您还没有遇到原子化,请尝试stringdoc$uri,看看会发生什么 忽略这一点,看起来您正试图使

返回

let $d := doc('foo.xml')

return concat('let $d := 

', $d)
我需要它返回:

let $d :=

bar

读取fn:concat的函数签名,没有理由期望它输出XML。从

也就是说,它接受可变数量的原子项并返回一个字符串。因此,如果您向它传递一个XML节点,它将尝试将其原子化并返回一个字符串结果。如果您还没有遇到原子化,请尝试stringdoc$uri,看看会发生什么

忽略这一点,看起来您正试图使用字符串操作构建一个XQuery表达式——可能是为了与xdmp:eval一起使用?这很好,但是不要使用xdmp:quote传入XML。出于正确性、性能和安全性的考虑,此作业的正确工具是外部变量

fn:concat(
  $arg1 as xs:anyAtomicType?,
  $arg2 as xs:anyAtomicType?,
  ...)
as xs:string
更好的是,将字符串部分作为单独的XQuery模块编写,并使用相同的外部变量参数调用它

为什么要这样做?正确性、效率和安全性。如果你养成了盲目计算字符串的习惯,那你就是在给自己制造麻烦。传递节点引用比引用大型节点更有效。当您将XML作为字符串引用时,可能会以XQuery重要字符结尾,例如{。然后您必须转义它们或切换到使用xdmp:unquote,但这会降低效率。任何转义都很容易出错。在SQL中,处理这一问题的经典方法是使用绑定变量,而在XQuery中,它是一个外部变量。与SQL中的绑定变量一样,外部变量处理转义。这也使得注入攻击更容易发生h更难。

使用管道连接。 例如:$a | |$b 如果变量是原子类型的,那么可以使用字符串联接。
例如:,$a | | fn:string join$b,,

回答您自己的问题似乎有点不公平:说堆栈交换一直明确鼓励用户回答他们自己的问题。不过,这可能不是最好的答案。如果您计划xdmp:eval该concat的结果,并且它包含任何大括号或其他XQuery语法,则可能会抛出错误或执行此操作如果攻击者可以控制XML,那么它就变成了一个注入攻击。它可能导致数据被盗或破坏。如果Fo.xml包含{xDMP:ReestXXDMP:主机,“HA!HA!”},会发生什么情况?例如,我不知道那篇自我回答的帖子!非常有趣。mblakele已经“警告”了您生成代码的可能危险,您打算评估这些代码,或者在没有中间控制的情况下执行这些代码。我对更大的图景感到好奇。我们可能能够建议其他的方法来阻止我们这是一段用于生成一些xquery以加载一些数据的一次性代码。然而,我对减少xquery注入感兴趣。目前我正在使用封装xquery的查询对象,并使用简单的字符串替换变量。有更好的方法吗?我肯定有-也许有一个库可以支持安全地替换查询中的值?如果通过转义特殊字符、先在XML中插入内容或其他方式,确保注入的值仅表示字符串,并且不允许过早关闭这些字符串,那么可以避免很多问题。也有一些特定于供应商的扩展可能会有所帮助。大多数XQuery解析rs(包括MarkLogic)允许使用eval类型函数,这通常也允许参数替换。除此之外,MarkLogic还支持xdmp:value(一种轻量级eval)和xdmp:unpath,以解析包含XPath类路径表达式的变量。
let $d := xdmp:quote(doc('foo.xml'))

return concat('let $d := 

', $d)
fn:concat(
  $arg1 as xs:anyAtomicType?,
  $arg2 as xs:anyAtomicType?,
  ...)
as xs:string
xdmp:eval('
  declare variable $INPUT external ;
  let $d := $INPUT
  return xdmp:describe($d)',
  (xs:QName('INPUT'), $d))