This little hack allows you to place XQuery, JavaScript, or SPARQL code blocks in org-mode files and evaluate them with babel using MarkLogic server.
I’m working on getting this package into MELPA.
- Put these files on your load path.
(require 'ob-ml-marklogic)
to load all of the language features. (Alternatively, require only the languages you need.)- Add some or all of
ml-xquery
,ml-javascript
, andml-xquery
to theorg-babel-load-languages
:(org-babel-do-load-languages 'org-babel-load-languages ; load all language marked with (lang . t). '((ml-xquery . t) (ml-javascript . t) (ml-sparql . t) …))
- Add the language/editing mode mappings to
org-src-lang-modes
:(add-to-list 'org-src-lang-modes '("ml-xquery" . xquery)) (add-to-list 'org-src-lang-modes '("ml-javascript" . javascript)) (add-to-list 'org-src-lang-modes '("ml-sparql" . sparql))
- Happy editing.
Most of the configuration is done with header arguments. These can be specified at any level. The following header arguments are supported:
:ml-curl
- The curl executable
:ml-host
- The MarkLogic hostname
:ml-scheme
- The URI scheme for requests
:ml-port
- The port for requests
:ml-eval-path
- The eval path
:ml-graphs-path
- The SPARQL eval path
:ml-auth
- Type of auth
:ml-username
- Username
:ml-password
- Password
:ml-output
- Output buffer
:ml-save-output
- Keep output buffer?
System defaults are
stored in ob-ml-common-default-header-args
in ob-ml-common.el
.
You’ll probably need to change some of them. The request URI is
constructed by concatenation:
:ml-scheme "://" :ml-host ":" :ml-port :ml-*-path
You’ll probably never need to change the :ml-eval-path
or
:ml-graphs-path
.
If you don’t specify :ml-auth
, then the requests will be made
without authentication. Setting :ml-save-output
will prevent the
temporary buffer that’s used to hold results from being deleted. That
can be useful if something goes wrong.
You can also pass query parameters and variables to the query using
the standard :var
header. Variable names that start with “&” are
passed to the eval endpoint. All other variable names are passed
through to the underlying query.
For example:
:var startDate="2017-04-19T12:34:57"
Specifying the variable startDate
passes it to the query (where it
can be accessed by declaring it external). Alternatively:
:var &database="Documents"
Specifying the variable &database
passes it to the eval endpoint.
You can specify as many variables as you wish. You’ll no doubt get errors if you pass things that the endpoint or query aren’t expecting. I have no idea how well my code plays with advanced org-mode features like reference to other named code blocks. If you see something weird, please open an issue.
Note: The GitHub rendering of this section is a bit misleading
as it elides the begin_src/end_src lines. Check the README.org
file for a more accurate picture.
XQuery:
xquery version "1.0-ml"; declare default function namespace "http://www.w3.org/2005/xpath-functions"; declare option xdmp:mapping "false"; declare variable $startDate external; let $date := $startDate cast as xs:dateTime let $diff := current-dateTime() - $date return current-dateTime() - $date
#+RESULTS: : -P347DT22H38.695693S
JavaScript:
var jsearch = require('/MarkLogic/jsearch.sjs'), collection = jsearch.collections, qbe = jsearch.byExample; collection('muppets') .documents() .where(qbe({ name: 'waldorf'})) .result();
#+RESULTS: : { : "results": null, : "estimate": 0 : }
SPARQL:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX c: <http://nwalsh.com/rdf/contacts#> PREFIX v: <http://nwalsh.com/rdf/vCard#> SELECT ?rdf WHERE { ?rdf rdf:type c:Thing }
#+RESULTS: { "head": { "vars": [ "rdf" ] }, "results": { "bindings": [ { "rdf": { "type": "uri", "value": "http:\/\/norman.walsh.name\/knows\/what\/DOM" } } ] } }
If the result is JSON or XML (and consists of a single part, it will be reformatted for legibility.)
let $_ := <doc><foo><bar><baz></baz></bar></foo></doc> return $_
#+RESULTS: : <doc> : <foo> : <bar> : <baz/> : </bar> : </foo> : </doc>
Kudos, complaints, bug reports, etc. most welcome. Please open an issue for bugs or observations of failure in my Emacs lisp style.