Abstract
Many projects have to manage a vast collation of information, from Web pages, mailing lists, project pages (such as SourceForge), project documentation, etc. There is even sometimes valuable resource in such overlooked areas as IRC logs and meeting notes. Very often this information is poorly integrated, and more importantly, it is hard for someone who ploughs through a cross-section of it to easily document the thread of resources that were most useful to them in a particular need. The 4Suite project, developing an open source XML processing platform written in Python and C had such a problem. The author set about to solve this problem by developing a sort of graph of interconnected information and documentation snippets using RDF for extensible relationships between these data snippets and key metadata.
The heart of the Akara is an RDF model. Some of the RDF model nodes are the URIs of hosted documents. Documents in several formats are supported, but a rich, Wiki-like text (Akara markup) is the usual default information entry format, so that users can enter marked-up information rapidly. This data is presented using a series of XML Stylesheet Transform Language (EXSLT) stylesheets with embedded RDF queries for extracting key metadata for each information node. The engine includes a Wiki text to XML translator which parses Wiki text and emits a SAX 2 stream of XHTML for further processing. The RDF Query is embedded in XSLT using the Versa query language ([VERSA]), which is designed with XSLT users in mind. The whole system works on a Representational State Transfer (REST) idiom of simple read and modify query driven by URLs using Web forms. Among the modifications possible are the re-organization of information nodes after initial entry, based on addition and alteration of RDF metadata. This gives the system some of the qualities of a Wiki, but reduces the labor intensiveness of information reorganization. Information nodes and updates can be annotated and commented upon by other users in a manner remeniscent of blogs. This presentation covers examples and details of all these processing steps.
The Akara is an open knowledge management tool that emphasizes casual information entry and later collation and organization. More importantly, it uses generic XML-related technologies for this purpose. This presentation provides the detail for attendees to undertake similar projects either for general use, or in particular organizatonal situations.
Keywords
Table of Contents
In late 2002, I decided that the best way to jump-start a good next generation of documentation for the 4Suite project was to find a way to collect snippets of information, instructions, examples and advice for users based on my own day-to-day experience. What I needed had the elements of FAQ. A user comes on the mailing list and asks a queston that was answered before, already, or which is a really good question whose answer should be highlighted. It had elements of a Weblog. I encounter a gotcha suitable for a diary entry, or an interesting snippet of information on the Web somewhere that I want to record for the benefit or interst of others. It had elements of a Wiki. I wanted it to be fairly easy to create assorted nodes of information, and to link them together. Just as importantly, I wanted to have the benefits of rich markup without the costs of having to edit tags by hand, or fiddle with through-the-web WSYWIG editors. And I wanted to make it easy for others to participate, by posting comments and for an authenticated subset of people to be able to edit information.
I didn't really find any package that approached this amalgam of ideas, so I decided to stich it together using basic Extensible Markup Language (EXSLT) and Resource Description Framework (EXSLT) technologies ([RDFINTRO1], [RDFINTRO2]). At first it was really just a publishing system for snippets edited directly into an RDF file, but it soon developed into a complete framework for simple, ad-hoc information management. The most direct inspiration was Wiki, and my favorite Wiki implementation is MoinMoin, by Jürgen Hermann ([MOINMOIN]). "Moin moin" is a Yoruba word for a meal made from boiled bean paste. There is a similar meal, called "Akara", popular for breakfast in Nigeria, made from fried rather than boiled bean paste. Hence the whimsical name of the project.
In this paper, I explain the workings of Akara, focusing on its use of general markup technologies, and specialized facilities of 4Suite. First I shall explain Akara from the user point of view, and then I shall detail the technologies that make it work.
The most important goal in Akara is to not lose sight of the fact that it centers around people rapidly entering rich content. This content could be edited into Web forms, but it should also be easily entered in an instant messaging console or an e-mail composer as well. This means that it needs the expressiveness of SGML-style tagged markup, but not the tedium. This is an old problem and has been solved by hundreds of people in hundreds of different ways. The Akara markup is a simplification of MoinMoin text, which is an embellishment of classic Wiki text. The following are some examples.
!This is a heading!
The last word in this sentence is in *bold*
The last word in this sentence is in /italics/
* This is a list item
** This is a sub-list item
** Another sub-list item
* Another list item
[This is a link to the XML Europe Home Page|http://www.xmleurope.com/]
Indented lines are treated as literal code blocks
def python_function()
return "hello world"
Or they can be delimited by marker lines
:::
def python_function()
return "hello world"
:::
This markup can be entered to add content through any of a variety of user interfaces, and Akara manages it as text in this form, and converts to tagged forms on the fly, as needed.
An Akara contains a collection of nodes. Each node is generally a block of Akara markup, the content, and some metadata. Each node has a type, and nodes can have relationships with each other, based on type. The relationships between nodes are themseles typed. This extremely generic model is what gives Akara its flexibility, just as the genericity and minimum of baked-in semantics in statements in an RDF model gives RDF its flexibility, and the same for the generic constructs in an XML grammar. But so that Akara users do not have to build all their systems atom by atom from this spare model, Akara does come with a core module of node types and relationships with particular behaviors attached to them. But Akara is designed to make extending and even modifying the core a very simple and natural process.
One built-in node is an Akara node, which delimits an entire collection of related information. There are also section nodes, which represent general topics of interest. There is also a "contains" relationship between akaras and sections. Sections in turn contain Item nodes, which consist of content, and basic metadata for that content. An item can represent a Weblog entry, a FAQ entry, a general note, or anything like. It is also easy to adjust the behaviors of these items to capture such nuances (for example, to split an item representing a FAQ entry into a question field and an answer field). Comment nodes can be attached to any of the other type of nodes, and generally represent comments and contributions by non-privileged users. There are a variety of edit and view user interfaces for each node type, and if you extend node types, you define the UI for them as well as the behavior.
Other features include an RSS feed of new items ([RSS10]), the ability to contribute content and receive update notifications using Internet Relay Chat (EXSLT) and e-mail, and a link aggregator that generates XML Bookmark Exchange Language (EXSLT) ([XBEL]), and sends notifications of potentially bad links.
Akara is a 4Suite application. 4Suite is a platform for XML and RDF operations. It handles the storage and processing of XML and RDF, largely using standard technologies. The idea is to make development of XML-based applications very easy, and indeed Akara itself is surprisingly little code. Akara is implemented as a series of XSLT scripts. One of the key features of 4Suite is its support for XSLT as a server-side processing platform. XSLT offers a very flexible extension mechanism, and 4Suite includes a library of built-in extensions which allow one to access the repository, RDF model and XML processing tools from XSLT scripts, and which provide some of the other facilities common to Web-based server-side scripting, from session management to Web forms processing.
While XSLT has its advantages as a Web scripting language, giving it as much added power as 4Suite does invites the danger of designs that mix content with presentation. In the scripts built into Akara, all the XSLT operations occur in two phases. In the model phase, the RDF and XML repositories are queried, session variables are checked, and so forth, using the specialized XSLT extension API for 4Suite. The result of the model phase is a simple XML format that contains all the material needed for presentation. This is then passed to the view phase, in which only pure XSLT instructions are used, as well as Community Extensions to XML Stylesheet Transform Language (EXSLT) community extensions, but no extensions proprietary to 4Suite. This makes the data and metadata in Akara very accessible, makes it easier to extend and customize the code, and in theory helps makes Akara portable to other toolkits. The hand-off from the model phase to the presentation phase is implemented using 4Suite's primitives for chaining one XSLT transform to another.
The following listing is a snippet from the model phase of the Akara built-in modules, and demonstrates the design sketched above.
<xsl:template name="show-akara">
<xsl:variable name="akara-info" f:node-set="yes">
<frdf:versa-query query="
distribute(@'{$node}', '. - dc:title -> *', '. - dc:description -> *')
"/>
</xsl:variable>
<xsl:variable name="title"
select='string($akara-info/List/List/List[1])'/>
<xsl:variable name="description"
select='string($akara-info/List/List/List[2])'/>
<a:akara url="{$fres:uri-path}">
<a:title><xsl:value-of select='$title'/></a:title>
<xsl:variable name="contents" f:node-set="yes">
<frdf:versa-query query="
distribute(@'{$node}' - a:contains -> *,
'.',
'. - dc:title -> *'
)
"/>
</xsl:variable>
<a:grouping>
<a:literal>
<w:render-akara-markup select='$description'/>
</a:literal>
</a:grouping>
<a:grouping>
<a:form a:layout="linear-2"
method='POST' action='{$akara-root-path}'>
<a:search/>
<a:account>
<xsl:choose>
<xsl:when test="fcore:has-session()">
<xsl:attribute name="logged-in">yes</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="logged-in">no</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</a:account>
</a:form>
</a:grouping>
<a:sections>
<xsl:for-each select='$contents/List/List'>
<a:section href="{a:public-url(*[1])}">
<a:title><xsl:value-of select='*[2]'/></a:title>
</a:section>
</xsl:for-each>
</a:sections>
</a:akara>
</xsl:template>
I shall break this listing down in order to explain it step by step.
<xsl:variable name="akara-info" f:node-set="yes">
<frdf:versa-query query="
distribute(@'{$node}', '. - dc:title -> *', '. - dc:description -> *')
"/>
</xsl:variable>
<xsl:variable name="title"
select='string($akara-info/List/List/List[1])'/>
<xsl:variable name="description"
select='string($akara-info/List/List/List[2])'/>
This snippet uses two 4Suite extensions to XSLT in order to perform a query on the RDF database and return the results in an XML orm that can be further processed in the script. The query is embedded in a variable, for easy access of the result, but normally the body of a variable yields a result tree fragment, not a node set, which means that node set operations cannot be performed on it. You can use an extension attribute, f:node-set, on variable and parameter instructions in order to make them construct a node set rather than a result-tree fragment of the results. This is equivalent to running the EXSLT exsl:node-set function on an RTF result.
The result is provided by a Versa query extension element, frdf:versa-query. The query given retrieves the title and description of the given Akara node ID. I won't delve to deeply into Versa in this document, but detailed explanations that cover all the queries I present can be had in my IBM developerWorks article on the query language ([VERSAINTRO]). Briefly, the distribute function allows me to perform multiple sub-queries on its first argument. The first argument is a resource literal. For example, in Versa the XML Europe Web site resource is written @'http://www.xmleurope.com/' (or, optionally, with double quotes instead). In this case the resource URI comes from XSLT using the fact that the query attribute's value is handled as an attribute value template (AVT), and therefore is retrieved from the XSLT variable $node, which is in turn determined from the URL that was accesed by the user. The subqueries are called traversal expressions, and start from the given resource and retrieve the value of its dc:title and dc:description properties. dc:title is a shortcut in Versa which will be familier to most RDF users. It is expanded to http://purl.org/dc/elements/1.1/title as long as the dc prefix is bound to http://purl.org/dc/elements/1.1/ in the host XSLT. The result of this query is an XML snippet such as the following:
<List>
<List>
<List>
<String>
Uche Ogbuji's Akara site on XML processing in Python
</String>
</List>
<List>
<String>
This site offers discussion and resources for XML processing in
Python, and augments
[the XML.com Python & XML column|http://www.xml.com/pub/au/84].
Akara -- An Akara is a series of notes, links, annotations and
sections. It is part blog, part Wiki, part HOWTO/FAQ wizard.
Akara is powered by [4Suite|http://4suite.org], XML and
[RDF|/uche.ogbuji.net/tech/rdf/].
Many items provide practical tips and instructions.
</String>
</List>
</List>
</List>
The result of a distribute is a list of lists, and the result of a traversal expression is a list, which expains all the nested lists. As you can see, the description is raw Akara markup (notice the indicated links), which gets translated to XHTML on the fly as I shall explain below.
<a:akara url="{$fres:uri-path}">
<a:title><xsl:value-of select='$title'/></a:title>
In the model phase, the outut is an XML file with all the relevant information from the model, which can be processed by the view. Here the beginnings of this output are generated. $fres:uri-path is a special top-level parameter by which 4Suite informs the script of the path portion of the user's requested URL.
<a:grouping>
<a:literal>
<w:render-akara-markup select='$description'/>
</a:literal>
</a:grouping>
A grouping is a way of organizing content without dwelling on presentation. Literal sections, on the other hand, are direct bits of final XHTML injected into the model output. In this case, it is the result of rendering the Akara markup for the node description using the w:render-akara-markup extension, which is defined in a Python module that comes with Akara.
<a:grouping>
<a:form a:layout="linear-2"
method='POST' action='{$akara-root-path}'>
<a:search/>
<a:account>
<xsl:choose>
<xsl:when test="fcore:has-session()">
<xsl:attribute name="logged-in">yes</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="logged-in">no</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</a:account>
</a:form>
</a:grouping>
Here you can see how the model specifies forms to be rendered by the user. This aspect of the code probably needs some refinement, and XForms is the likely approach for improving things. The form specification is given a layout ID, which is rendered using a particular page arrangement in the view, and can thus be easily be customized by the user. Non-prefixed attributes are basically what the HTML form will use, and are usually passed on verbatim in the view. The $akara-root-path is set up in an Akara parameter as the root URL path of the current Akara: forms are processed by applying an XSLT script to this generic base path, and the script's path is specified in an HTML hidden input parameter. a:search is a special designation for the portion of the form that allows the user to search. a:account designates a section with some links for Akara editors to log in, log out, or perform administrative tasks. The fcore:has-session() extension function is standard with 4Suite and and checks whether the user has a current session created after a log in.
<xsl:variable name="contents" f:node-set="yes">
<frdf:versa-query query="
distribute(@'{$node}' - a:contains -> *,
'.',
'. - dc:title -> *'
)
"/>
</xsl:variable>
<a:sections>
<xsl:for-each select='$contents/List/List'>
<a:section href="{a:public-url(*[1])}">
<a:title><xsl:value-of select='*[2]'/></a:title>
</a:section>
</xsl:for-each>
</a:sections>
</a:akara>
</xsl:template>
This final portion provides the data for the listing of sections for the gven Akara. Another Versa query retrieves the needed data from RDF, this time the resource ID and title of each of the children of the Akara node (determined from values of its a:contains properties). The a:public-url() function is an Akara tool to translate RDF IDs of Akara nodes (which are of the form ftss:///akara/nodes/2003-01-01/pyxml-akara) into relative URLs suitable for links on the page (/akara/nodes/2003-01-01/pyxml-akara). ftss is a custom URL scheme for accessing resources in the 4Suite repository.
An example of output of the model phase is in Appendix A. The hand-off from the model phase script to the view phase is accomplished by using the f:chain-to extension element, as follows:
<f:chain-to href="{$presentation-xslt}"/>
Where href is a link to the stytlesheet that controls the view phase, which comes from a user parameter. Some people feel that embedded references to the presentation in the model is bad coupling. While I don't really agree, as long as the reference come from a parameter (unlike, say the xml-styleshet processing instruction), 4Suite also allows you to completely de-couple this connection by specifying the chaining in the server configuration file, or even in the rendered links.
The following snippets come from the view phase of the Akara built-in modules, and works with the output of the model phase as described above.
<xsl:template name="main-template">
<xsl:param name="title"/>
<xsl:param name="body"/>
<html>
<head>
<title><xsl:value-of select='$title'/></title>
<link rel='stylesheet' href='$akara-css' type='text/css'/>
</head>
<body>
<xsl:copy-of select='$body'/>
<hr/>
<div style="vertical-align: middle;">
<a href="http://4Suite.org">
<img width="150" height="65" border="0"
src="/ftss/dashboard/images/poweredby_4ss.png"
alt="Powered by 4Suite"/>
</a>
<span style="width: 100%"> </span>
<!-- the following URL is munged for formatting -->
<a href="http://feeds.archive.org/validator/check
?url={$akara-root-path}/akara/nodes/2003-01-01/pyxml-akara
?xslt=/akara/rss.xslt">
<img src="{$akara-root-path}/images/valid-rss.png" border="0"
alt="[Valid RSS]" title="Validate my RSS feed"
width="88" height="31"/>
</a>
</div>
</body>
</html>
</xsl:template>
This is the default rendering page template that comes with Akara. You can see how it is used in the default view for most Akara nodes:
<xsl:template match="a:main|a:akara|a:section|a:item">
<xsl:call-template name="main-template">
<xsl:with-param name="title" select="a:title"/>
<xsl:with-param name="body">
<h1><xsl:value-of select="a:title"/></h1>
<xsl:apply-templates/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
Groupings have a pretty straightforward default view: as divisions separated by horizontal rules:
<xsl:template match='a:grouping'>
<div>
<xsl:apply-templates/>
</div>
<xsl:if test="position() != last()">
<hr/>
</xsl:if>
</xsl:template>
The rest of the rendering, besides the forms (hwich I don't cover here) is also very straightforward:
<xsl:template match='a:akara' mode="brief">
<a href="{@href}"><xsl:value-of select='a:title'/></a>
<blockquote>
<xsl:copy-of select='a:description/node()'/>
</blockquote>
</xsl:template>
<xsl:template match='a:sections'>
<h3>Sections:</h3>
<xsl:apply-templates mode="brief"/>
</xsl:template>
<xsl:template match='a:section' mode="brief">
<div>
<a href="{@href}"><xsl:value-of select='a:title'/></a>
</div>
</xsl:template>
The output of the rendering phase is valid HTML 4.0.1, and there are numerous avenues for user customization based on structural or style considertions.
The Akara's design doesn't conjure up any ground-breaking ideas, but it does build on the fundamental extensibility of technologies such as XML, RDF and REST architecture in ways that I think are unfortunately rare. Nodes are abstract structures in RDF, with human content literals maintained in the most friendly forms possible. They are accessed in a declarative, rules-based manner that is easy to customized, generating a simple XML represenation that can be rendered for display on a Web browser, RSS news reader, IRC, e-mail, and other media. There are plans in the works to extend Akara management and reading to other formats such as Web services, CORBA/Bonobo (for friendly GNOME intefaces) and XPCOM (for nice Mozilla tools). Such adaptations are made much simpler because of the simpicity of the design, and the many XML and RDF processing facilities offered in the 4Suite toolkit.
Here is an example of the output from the model phase of the Akara implementation. You can see how the default presentation of this view on the main page of Python/XML Akara (http://uche.ogbuji.net/tech/akara/nodes/2003-01-01/pyxml-akara).
<?xml version="1.0" encoding="utf-8"?>
<a:akara xmlns:a="http://uche.ogbuji.net/tech/projects/akara/"
xmlns="http://www.w3.org/1999/xhtml"
url="/uche.ogbuji.net/tech/akara/nodes/2003-01-01/pyxml-akara"
>
<a:title>Uche Ogbuji's Akara site on XML processing in Python
</a:title>
<a:grouping>
<a:literal>
<p>This site offers discussion and resources for XML processing
in Python, and augments <a href="http://www.xml.com/pub/au/84">the
XML.com Python & XML column</a>. </p>
<p>Akara -- An Akara is a series of notes, links, annotations
and sections. It is part blog, part Wiki, part HOWTO/FAQ wizard.
Akara is powered by <a href="http://4suite.org">4Suite</a>,
XML and <a href="/uche.ogbuji.net/tech/rdf/">RDF</a>. </p>
<p>An akara is divided into sections, each of which has a set
of items. Sections and items can have comments attached to them.
The idea is that each item tries to cover a single coherent topic
from the point of view of a particular author. Many items provide
practical tips and instructions. </p>
</a:literal>
</a:grouping>
<a:grouping>
<a:form action="/uche.ogbuji.net/tech/akara/"
a:layout="linear-2" method="POST">
<a:search/>
<a:account logged-in="no"/>
</a:form>
</a:grouping>
<a:sections>
<a:section href="
/uche.ogbuji.net/tech/akara/nodes/2003-01-01/4suite-dev-section
">
<a:title>Information for 4Suite developers</a:title>
</a:section>
<a:section
href="/uche.ogbuji.net/tech/akara/nodes/2003-01-01/4suite-section">
<a:title>Information for 4Suite users</a:title>
</a:section>
<a:section
href="/uche.ogbuji.net/tech/akara/nodes/2003-01-01/general-section">
<a:title>Python and XML in general</a:title>
</a:section>
</a:sections>
</a:akara>
[AKARA] Akara project home page http://uche.ogbuji.net/tech/rdf/akara/
[4SUITE] 4Suite http://4Suite.org
[RDFINTRO1] U. Ogbuji, An introduction to RDF, http://www-106.ibm.com/developerworks/xml/library/w-rdf/
[RDFINTRO2] U. Ogbuji, The Languages of the Semantic Web, http://www.newarchitectmag.com/documents/s=2453/new1020218556549/index.html
[MOINMOIN] J. Hermann, MoinMoin Project Homepage, http://moin.sf.net/
[XBEL] The XML Bookmark Exchange Language (XBEL), http://xml.coverpages.org/xbel.html
[VERSA] The Versa Home Page, http://uche.ogbuji.net/tech/rdf/versa/
[VERSAINTRO] U. Ogbuji, RDF Query using Versa, http://www-106.ibm.com/developerworks/xml/library/x-think10/index.html
[RSS10] RDF Site Summary (RSS) 1.0 http://web.resource.org/rss/1.0/
[REST] REpresentational State Transfer (REST) http://internet.conveyor.com/RESTwiki/moin.cgi/
![]() ![]() |
Design & Development by deepX Ltd. |