Xidel as static site generator
=============

Xidel can be used to generate static web pages using XQuery.

The great thing about XQuery is that a standard XQuery expression looks just like an HTML page template. For example

    <html><body>
      <div>{$content}</div>
    </body></html>

is an XQuery expression that returns an HTML page with $content inserted in the middle of it.

This works in any XQuery processor, but it is processor specific how to call the processor, how to declare a variable like $content and how to write the query result (i.e. the generated page) to a file. This example shows how to do that in Xidel. In this readme we describe all generating files, and the final site can be seen in the _publish subdirectory:

Storing the content: *.xml
-------------------------

We store the content in XML files. They have the advantage that you can write all the content just as you would write it in an HTML file, but you can also use additional, user-defined tags.

For every page the final website should have, we have one XML file with the content.  In this example, index.xml and page2.xml, which become index.html and page2.html on the generated site (see _publish directory). Here each of those files has one `<content>` element, which contains the content, and `<title>`, `<head>` elements with meta information.

There is one additional XML file global.xml which contains a list of all pages: for each the name of their XML file and a title for the navigation in a `<fileinfo>` element.

Storing the template/XQuery layout: style.xq.html
--------------------------

The layout is stored in style.xq.html . Despite the extension .html it is an XQuery expression, but calling it html let us view the basic structure in a browser.

style.xq.html needs three variables, `$global`, which is global.xml,  `$file` which is the current content file, and `$fileinfo`, which is the element from global.xml that describes the current file.

The contained XQuery expressions are straightforward, `{...}` expressions are used to insert the content at the appropiate positions in the HTML.

Only the expression in the `<div id="navigation">` is non-trivial, we use an XQuery-for loop to iterate over the elements in $global, and create from them a link to each generated page.


Declaring the variables
---------------------

The standard XQuery way to define dynamic variables is to put `declare variable $content external;` at the top of the query. However, it still implementation-defined how the value is defined, so we are not using that approach.

Instead we are using Xidel's global variables. Just writing `$variable := ...` to set one. See common.xq in the next section.

Calling Xidel: common.xq and the Makefile 
---------------------

To call Xidel we use a standard Makefile, so the entire site can be generated by calling GNU `make`. Make's dependancy tracking ensures that after every change only the affected HTML pages are remade. The structure of the Makefile is probably the most complicated part of this example as it is a multi-stage Makefile.

First it calls Xidel to call the XQuery function `local:deps()` from common.xq. This opens the XML file global.xml and writes a list of all HTML files that should be generated to buildtemp/global.d. This means the Makefile does not contain the list of files of the site, so you do not need to modify the Makefile to add new pages. Just use this Makefile unchanged for all your websites (except for the upload destination). 

Afterwards it calls Xidel for each of these pages, sets the variable `$source` to the name of the content XML and calls the function `local:doit()` from common.xq. `local:doit()` contains the actual transformation code. First it loads the relevant files using `doc` and `file:read-text` functions, declares the `$file` and `$fileinfo` variables, evaluates the style XQuery expression using `eval` and finally writes the output. Pay attention to the prefixes of the function names. Functions starting with `local:` are declared in common.xq (look them up), functions without prefix are standard XQuery functions, functions with `file:` are part of the standard EXPath file module and functions with `x:` are Xidel specific extensions. Thus all functions except `x:` should be supported by every standard XQuery processor.

The Makefile contains additional statements to clean temporary files and to detect changed files to upload them.


More examples
-----------------

The above describes all of this example.

For a larger example you can look at my webpage (repository benibela/site). My website uses more complex techniques like generating multiple HTML pages from a single XML file, internal link ids, and XQuery transformations for more dynamic content files. (E.g. replacing `<insert value="currentyear"/>` with the current year) 