External variables are even lazier than string concatenation is. When you use an external variable, you protect your code from injection attacks, and you also avoid having to escape significant characters.
Laziness is good. -- Mike Andy Townsend wrote:
Hi David,I like your solution. Whenever I have used xdmp:eval to date I have preformed a string literal to pass i rather than employ external variables - it feels slightly lazy but easy.The only downside I know to using that method to construct the string is if the string actually contains XQuery { } syntax that you _dont_ want evaluated until you execute the xdmp:eval - such as if you were setting a variable from the other DB and using it as a part of your evaluated query. A bit contrived but something like this.....let $query := <q> let $localdbval := /abc/def/ghi[1] myfunc(<anode>{$localdbval}</anode>) </q>where rather than remembering to escape quotes you'll have to escape braces, using double braces.AndyDavid Sewell <[EMAIL PROTECTED]> Sent by: [EMAIL PROTECTED]18/07/2007 19:59 Please respond to General Mark Logic Developer Discussion <[email protected]> To General XQZone Discussion <[EMAIL PROTECTED]> cc Subject [MarkLogic Dev General] Taming xdmp:eval() syntax We have been somewhat loathe to use xdmp:eval() because of its rather ungainly syntax, what with having to define external variables and use the <options><database>..</database></options> structure to pass a database ID to the function. I'd like feedback on an alternate way of calling the function that I've just been trying out. Suppose I have a database named "Shakespeare" containing hamlet.xml. It is not the default database for my app server, so I'll need to access it using xdmp:eval(). I want to return all lines spoken by Hamlet containing the word "slave", then all lines containing "fool". (For purposes of the exercise I'll call cts:search twice rather than use an 'or' query.) Here's what I'd call the typical way to construct the query: let $terms := ("slave", "fool") for $search in $terms return xdmp:eval( ' define variable $SEARCH as xs:string externalcts:search(doc("hamlet.xml")//speech[speaker[.="HAMLET"]]/line, $SEARCH)', (QName("", "SEARCH"), $search), <options xmlns="xdmp:eval"> <database>{xdmp:database('Shakespeare')}</database> </options> ) where the query string is passed to xdmp:eval() as a literal string. That does the job and is compact, but somewhat unreadable. Plus you have to be careful to escape any ' used within the query. Here is an alternate way of doing the same thing, longer but more readable, producing the exact same results: define variable $ShakespeareDB { <options xmlns="xdmp:eval"> <database>{xdmp:database('Shakespeare')}</database> </options> } let $terms := ( "slave", "fool" ) for $search in $terms let $query := <q>cts:search(doc("hamlet.xml")//speech[speaker[.='HAMLET']]/line, "{$search}")</q> return xdmp:eval( $query, (), $ShakespeareDB ) Here I'm defining the options node as a global variable, which of course makes sense if I want to use the same options in more than one xdmp:eval(). The main novelty is passing the query parameter to xdmp:eval() as a variable containing a constructed <q> element, which is cast as a string by xdmp:eval(). Because $query is a constructed element, I can use standard XQuery { } syntax to embed variable references that are expanded before $query is passed to xdmp:eval(), so "{$search}" ==> "slave" then "fool" I'm getting the effect of external variables within xdmp:eval() without the messiness of the external variables syntax. Can anyone see a downside to this approach? ------------------------------------------------------------------------ _______________________________________________ General mailing list [email protected] http://xqzone.com/mailman/listinfo/general
smime.p7s
Description: S/MIME Cryptographic Signature
_______________________________________________ General mailing list [email protected] http://xqzone.com/mailman/listinfo/general
