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

', $d)
回報的XQuery CONCAT預期的方式不輸出文檔的XML
let $d :=
bar
我需要它返回:
let $d :=
<foo>bar</foo>
let $d := doc('foo.xml')
return concat('let $d := 

', $d)
回報的XQuery CONCAT預期的方式不輸出文檔的XML
let $d :=
bar
我需要它返回:
let $d :=
<foo>bar</foo>
閱讀fn:concat
函數簽名,沒有理由期望它輸出XML。從http://www.w3.org/TR/xpath-functions/#func-concat
fn:concat(
$arg1 as xs:anyAtomicType?,
$arg2 as xs:anyAtomicType?,
...)
as xs:string
也就是說,它需要可變數量的原子項並返回一個字符串。所以如果你把它傳遞給一個XML節點,它會嘗試將它原子化並返回一個字符串結果。如果您尚未進入霧化,請嘗試string(doc($uri))
以查看會發生什麼。
忽略這一點,它看起來像你試圖建立一個使用字符串操作的XQuery表達式 - 可能用於xdmp:eval
?這很好,但不要通過使用xdmp:quote
來傳遞XML。爲了正確性,性能和安全性的原因,這項工作的正確工具是一個外部變量。
xdmp:eval('
declare variable $INPUT external ;
let $d := $INPUT
return xdmp:describe($d)',
(xs:QName('INPUT'), $d))
更好
然而,寫入字符串部分作爲單獨的XQuery模塊和相同的外部變量參數xdmp:invoke
它。
爲什麼這樣呢?正確性,效率和安全性。如果你養成了盲目評估琴絃的習慣,那麼你正在設法解決問題。傳遞節點引用比引用大型節點更有效。當您將XML引用爲字符串時,您最終可能會使用XQuery重要字符,例如{
。然後你必須逃避它們(或切換到使用xdmp:unquote
,但這使得它效率更低)。任何轉義都將容易出錯。在SQL中,處理這種情況的經典方法是使用綁定變量,而對於XQuery,它是一個外部變量。與SQL中的綁定變量一樣,外部變量處理轉義。這也使得注入攻擊變得更加困難。
使用管道連接。 例如:$ a || $ b 如果您的變量屬於原子類型,那麼您可以使用字符串連接。 例如:,$ a || fn:string-join(($ b),「,」)
mblakele已經'警告'您足夠了解生成代碼的可能危險,您打算評估或執行沒有中間控制。我很好奇,但更大的圖片。我們可能會建議替代路線,這將防止使用有風險的方法.. – grtjn
這是一個一次性代碼生成一些xquery來加載一些數據。然而,我對緩解XQuery注入感興趣。目前我正在使用封裝xquery的「查詢對象」,並對變量使用直接的字符串替換。有沒有更好的辦法? (我確定有 - 可能是一個庫來支持查詢中值的安全替換?) – Ben
那麼,如果確保注入的值只代表字符串,並且不允許,則可以防止很多問題過早關閉這些字符串,通過轉義特殊字符,首先在XML中插入事物,或其他。有一些供應商特定的擴展可能也有幫助。大多數XQuery解析器(包含MarkLogic的解析器)允許使用eval類型的函數,這些函數通常也允許參數替換。除此之外,MarkLogic還支持xdmp:value,一個輕量級的eval以及xdmp:unpath,用於解析存放XPath路徑類表達式的變量。 – grtjn