I have just started learning the eXist database and am intrigued by the REST api built into it.
The application that I am using requires querying a file and then applying an xslt stylesheet to the result, but the REST api is not returning the correct media type (text/html). I am using the _xsl
and _query
parameters (along with _wrap=no
to avoid eXist wrapping results when using _query
).
According to eXist by Erik Siegel and Adam Retter (O'Reilly, 2014), when using the _xsl
parameter,
Applying an XSLT stylesheet in this manner always changes the response's Internet media type to text/html.
(page 98, bold added by me), however, I am getting back application/xml (confirmed using the LiveHTTPHeaders plugin in Firefox).
Consider the following documents in the database
<items>
<item>This is item 1</item>
<item>This is item 2</item>
</items>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<head><title>Testing</title></head>
<body>
<ul>
<xsl:apply-templates select="*"/>
</ul>
</body>
</html>
</xsl:template>
<xsl:template match="items">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="item">
<li><xsl:value-of select="."/></li>
</xsl:template>
</xsl:stylesheet>
Then this url (applying the stylesheet to the whole document)
http://localhost:8080/exist/rest/db/apps/testing/example.xml?_xsl=/db/apps/testing/example.xsl
returns an html page (which is correctly rendered as the media type is text/html), but this url (first selecting only one item element and then applying the stylesheet)
http://localhost:8080/exist/rest/db/apps/testing/example.xml?_query=/items/item[1]&wrap=no&_xsl=/db/apps/testing/example.xsl
returns an xml file (application/xml)
<html>
<head>
<title>Testing</title>
</head>
<body>
<ul>
<li>This is item 1</li>
</ul>
</body>
</html>
The result here is correct, but it is served with the wrong media-type.
It seems that adding the _query
parameter in order to first select only part of the document causes the media-type to be application/xml instead of text/html, and the behavior described by Siegel and Retter is only true if the _xsl
parameter occurs by itself.
Is there a way to cause the second url which first filters the file to return text/html as well? Or is this behavior impossible with the REST api?
(Note: I know that I can pass parameters to an XQuery script and have that script both filter and transform the data, but I am interested in using the REST api to do the work here if possible.)
I looked at the code of eXist and do not see any way to get the results you want by using a GET
request on the REST interface. However, you can do a POST
. Here is an illustration of how it can be done using wget
. Note that whereas you put your files under /db/apps/testing/
, when I uploaded your files to my eXist instance for testing I put them under /db/testing/
(no apps
). Adjust the paths as needed in what follows.
Create a file named post.xml
with the following:
<?xml version="1.0" encoding="UTF-8"?>
<query xmlns="http://exist.sourceforge.net/NS/exist"
wrap="no">
<text>/items/item[1]</text>
<properties>
<property name="stylesheet" value="/db/testing/example.xsl"/>
<property name="media-type" value="text/html"/>
</properties>
</query>
Then issue this command:
wget -S --post-file=post.xml --header='Content-Type: application/xml'
http://localhost:8080/exist/rest/db/testing/example.xml
Or the equivalent. You need to have the content of post.xml
as the content of the POST
request, and the Content-Type
header must be application/xml
. The -S
option dumps the response headers to the screen. So when I run the above, I get this on the console:
--2016-06-15 12:12:10-- http://localhost:8080/exist/rest/db/testing/example.xml
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:8080... connected.
HTTP request sent, awaiting response...
HTTP/1.1 200 OK
Date: Wed, 15 Jun 2016 16:12:10 GMT
Set-Cookie: [...]
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Last-Modified: Tue, 14 Jun 2016 12:21:56 GMT
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Server: Jetty(8.1.9.v20130131)
Length: unspecified [text/html]
Saving to: ‘example.xml’
example.xml [ <=> ] 154 --.-KB/s in 0s
2016-06-15 12:12:10 (6.67 MB/s) - ‘example.xml’ saved [154]
Note how the response's Content-Type
is text/html
. wget
saves the results in a local file named example.xml
which contains the expected data:
<html>
<head>
<title>Testing</title>
</head>
<body>
<ul>
<li>This is item 1</li>
</ul>
</body>
</html>