3

This is a followup question to

Getting hold of tag content in XQuery 3.0 (exist-db)

Assume that such an xquery script should be able to return the result as XML, JSON or HTML base on a query parameter like

http://host/exist/rest/db/myscript.xql?mode=xml|html|json

I know how to change the serializer from XML -> JSON and how to apply an XSLT transformation using transform:transform().

What is the best approach for encapsulating the XML generation for result and then transforming it based on the request parameter into one of output formats?

xquery version "3.0";

module namespace services = "http://my/services";

import module namespace transform = "http://exist-db.org/xquery/transform";
declare namespace rest = "http://exquery.org/ns/restxq";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

declare
    %rest:GET
    %rest:path("/data.html")
    %output:media-type("text/html")
    %output:method("html5")
function services:home() {
    transform:transform(services:example1(), doc("/db/my-xml-to-html.xslt"), ())
};

declare
    %rest:GET
    %rest:path("/data.json")
    %rest:produces("application/json")
    %output:method("json")
function services:home-json() {
  services:example1()
};

declare
    %rest:GET
    %rest:path("/data.xml")
    %rest:produces("application/xml")
function services:home-xml() {
  services:example1()
};

declare
    %private
function services:example1() {
    <some>
       <data>hello world</data>
    </some>
};

1 Answers1

4

I would suggest taking a look at RESTXQ in eXist, as this allows you to easily control the result format based on content negotiation or any other HTTP parameters or headers. For example using content negotiation to produce XML, JSON and HTML manifestations:

xquery version "3.0";

module namespace services = "http://my/services";

import module namespace transform = "http://exist-db.org/xquery/transform";
declare namespace rest = "http://exquery.org/ns/restxq";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

declare
    %rest:GET
    %rest:path("/data")
    %rest:produces("text/html")
    %output:method("html5")
function services:home() {
    transform:transform(services:example1(), doc("/db/my-xml-to-html.xslt"), ())
};

declare
    %rest:GET
    %rest:path("/data")
    %rest:produces("application/json")
    %output:method("json")
function services:home-json() {
  services:example1()
};

declare
    %rest:GET
    %rest:path("/data")
    %rest:produces("application/xml")
function services:home-xml() {
  services:example1()
};

declare
    %private
function services:example1() {
    <some>
       <data>here</data>
    </some>
};
adamretter
  • 3,885
  • 2
  • 23
  • 43
  • If you wanted to do the content negotiation based on the URI rather than using the `Accept` HTTP header as above, you could instead do something like - declare %rest:GET %rest:path("/data.html") %output:method("html5") %output:media-type("text/html") function services:home() { (: etc... :) – adamretter Jul 02 '14 at 09:51
  • I take from the configuration that the location of the script above does not matter. In this case a HTTP GET to http://host:port//exist/rest/db/data.html (or /data for the original code) is supposed to return the ... fragment? However this does not work. The server just returns a 200 response with empty payload. RestXqTrigger is enabled in /db/system/config/db/collection.xconf –  Jul 02 '14 at 12:22
  • 1
    @user3790407 If I am not mistaken, eXist by default maps RestXQ to `exist/restxq`, so your URL would look like `http://host:port/exist/restxq/data` – dirkk Jul 02 '14 at 12:38
  • Not directly..see my update with my RESTXQ code above. Calling http://host.port/exist/restxq/data.html gives me: HTTP ERROR 405 Problem accessing /exist/restxq/data.html. Reason: HTTP method GET is not supported by this URL –  Jul 02 '14 at 14:14
  • @AndreasJung I think ideally you should have opened a new questions for this as now your question does not make a lot of sense. However, you should consult the restxq log file to understand whether your query is being added to the registry or not. – adamretter Jul 04 '14 at 11:07