When developing monet, a flexible monitoring tool for the VoDka project, we needed a way of generating monet output to different devices: standard browsers, text-only browsers, wap-enabled terminals, and so on. Generating monet output as XML documents and then transforming them using an XSL engine with rules to choose the appropriate XSL style became an elegant and effective solution.
You should install the XSL engine (for instance, sablotron_adapter) in first place.
Before compiling mod_xsl, you should make available the include httpd.hrl.
ln -s %%ERLANG_SOURCES_PATH%%/lib/inets-2.5.X/httpd.hrl src/httpd.hrlThen, compile mod_esi:
make
To check if mod_xsl is working you can use the examples provided in the priv directory. Type from Unix shell:
make test erl -config priv/server_root/inetsChange the configuration priv/server_root/conf/httpd.conf in order to set the correct parameters for the XSL engine
XslEngine sablotron_xsl_engine /usr/lib/erlang/lib/sablotron_adapter-1.1/bin/sablotron_adapterfrom Erlang shell:
code:add_path("./ebin"). code:add_path("./priv/server_root/src"). application:start(inets).try the following URLs:
http://localhost:8001/erl/test/employees http://localhost:8001/erl/test/staffmember http://localhost:8001/erl/test/publications
Check if the installation directory is set properly and then:
make install
mod_xsl needs a module to perform the actual XSL tranformation. The selection of the XSL Engine is established with the XslEngine directive:
XslEngine XSL_ENGINE INIT_STRING
where XSL_ENGINE is an Erlang module implementing the XSL Engine and INIT_STRING is a string for the initialization of the engine (XSL_ENGINE:start(INIT_STRING)). For instance, if sablotron_adapter is used as XSL Engine, the configuration file should have:
XslEngine sablotron_xsl_engine SABLOTRON_ADAPTER_PATH
where SABLOTRON_ADAPTER_PATH is the path of the port adapter for the sablotron library.
In order to choose the approriate XSL stylesheet, mod_xsl must be configured with
a set of rules to establish the selection procedure. The rules are declared in the
inets configuration file with the XslRules directive:
XslRules RULEPATH (RULEFILE)+
where RULEPATH is the base path for the rules files and RULEFILE is a collection of rules with the following format:
{ENTITY, DESCRIPTION, MIMETYPE, XSLFILE, CONDITION}.
All the rules for the current document type are checked sequentially; the first matching rule will be applied. If none, the content type text/xml; doctype=DOCTYPE is added to the response header.
The dictionary [{Key,Value}] used for testing the predicates is initially built from both query string parameters and http header; the XslHook directive allows applications to change/delete/add {Key,Value} pairs. XslHook HookModule HookFunction
where HookFunction/1 is exported in HookModule. The parameter of this function is the current dictionary and it delivers a (maybe) modified version. This mechanism allows, for instance, to include application dependant information (such as user preferences) based upon some parameter already present in the dictionary such as a session identifier. The following example illustrates the idea:
add_user_preferences(Dict) -> case httpd_util:key1search(Dict, "session_id") of undefined -> Dict; %% no session SessionId -> get_application_dependant_preferences(SessionId) ++ Dict end.
Thus, application-dependant {Key,Value} can be added to the XSL context (say, for example, [{"news_style","verbose"}, {"frames","no"}]). For debugging purposes, a hook is included with mod_xsl; it prints out the current dictionary.
XslHook xsl_debug_hook show
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" ++ "<!DOCTYPE employees>" ++ TheRestOfTheXmlDocumentYa, I could flatten the whole response and convert the binaries to lists, but that is quite expensive if documents are large 8-{