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 external
      cts: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?

-- 
David Sewell, Editorial and Technical Manager
ROTUNDA, The University of Virginia Press
PO Box 801079, Charlottesville, VA 22904-4318 USA
Courier: 310 Old Ivy Way, Suite 302, Charlottesville VA 22903
Email: [EMAIL PROTECTED]   Tel: +1 434 924 9973
Web: http://rotunda.upress.virginia.edu/
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general

Reply via email to