Version history: |
|
| 2001-01-25 - | Version 0.7 |
| 2001-07-11 - | Version 0.8 |
| 2003-12-09 - | Version 0.85 |
| 2004-06-23 - | Version 0.86 |
| 2004-08-12 - | Version 0.87 |
| 2005-03-01 - | Version 0.88 |
| 2005-05-27 - | Version 0.89 |
| 2005-11-09 - | Version 0.9 |
| 2006-08-24 - | Version 0.91 |
| 2011-09-27 - | Version 0.91 Patched |
2011-12-09 - |
Version 1.0 |
RuleML has been designed for the interchange of the major kinds of Web rules in an XML format that is uniform across various rule languages and platforms. It has broad coverage and is defined as an extensible family of languages, whose modular system of schemas permits rule interchange with high precision.
The scope of this specification covers
The scope of this specification does not cover tools that make use of RuleML languages, such as parsers, inference engines or editors. For a listing of such tools, see the RuleML Implementations wiki page.
RuleML Version 1.0 is a "Rosetta Stone" release where two schema languages, XSD and Relax NG, are independently employed to formalize the syntax, to the extent possible within each language. See Design and Implementation of Highly Modular Schemas for XML: Customization of RuleML in Relax NG (RuleML in Relax NG) and the RuleML MYNG Wiki page for the details of this re-engineering effort. MYNG is an acronym for "Modular sYNtax confiGurator", or "Modularize Your NG", and may be pronounced either "ming" or "my N G".
The RuleML Version 1.0 XSD schemas are a minor modification of the patched XSD schemas of RuleML Version 0.91, which follow the tree-based modularization approach. A procedure for validation against the XSD schemas is described in Appendix 3.
The RuleML Version 1.0 Relax NG schemas are a new component of the RuleML Version 1.0 release, and are intended to replace the hand-written XSD schemas in future releases. The Relax NG schemas are available for two serializations, "normal" and "relaxed", and follow a lattice-based modularization (RuleML in Relax NG). The relaxed-form serialization is permissive relative to the grammar given in the Content Models document, i. e. every RuleML Version 1.0 instance that is valid with respect to the Content Models document will validate against the relaxed serialization Relax NG schemas. The normal serialization Relax NG schemas validate instances in the normal form, which is described in the Normalizer section. Procedures for validation against the Relax NG schemas is described in Appendix 5.
Note that the DTD specification of RuleML is no longer being maintained, but will continue to be available as an archive. Tools capable of converting between XML Schema and DTDs such as XMLSpy are always available.
An introduction to RuleML is given in our Primer. Also, the paper Overarching discusses the upper layer of the RuleML hierarchy of rules. In that terminology, the system of RuleML languages presented here only covers derivation rules, (see the official model).
This is because we think it is important to start with a subset of simple rules, test and refine our principal strategy using these, and then proceed to more general categories of rules in the hierarchy (deliberation rules), as well as to other kinds of rules (reaction rules).
A comprehensive Glossary accompanies this specification.
The grammar of RuleML Version 1.0 is partially described in the Content Models document, where the content model of each individual element is compared across the named sublanguages, as specified within the XSD Schemas. The RuleML grammar is also partially described by the Relax NG Schemas.
Below is a summary of the changes in RuleML Version 1.0:
<head> and <body>, replaced with <then> and <if>, respectively
<lhs> and <rhs>, replaced with <left> and <right>, respectively
<Hterm> and <Con>, replaced with <Uniterm> and <Const> respectively
@in ="no|semi|yes" with respective values, replaced with @per ="copy|open|value"@uri, for URIs, replaced with @iri, for IRIs
<act> introduced as optional wrapper of all performatives (e.g. <Assert>) in the <RuleML> element
Readers who already know RuleML Version 0.91 may want to refer to the Changes section.
Numerous sample RuleML documents have been prepared and maintained; some exemplify features of RuleML and are useful didactically while others are mostly for testing puposes. Updated examples (e.g., own.ruleml and reify.ruleml) accompany the RuleML Version 1.0 release and can be found with all the others in the Examples directory. The following examples are new:
@iri attribute,
Examples from previous versions of RuleML are also maintained, e.g. 0.91 examples).
Continuing the practice begun in 0.86, an XSLT stylesheet named 091-to-100.xslt has been created to automatically update RuleML Version 0.91 documents to RuleML Version 1.0. For instance, taking the discount example from 0.91 as input, the stylesheet outputs the following: discount_100.ruleml. Additional translation output samples are found in the Upgrader directory.
Upgrader transformation can be accomplished using a web-based XSLT tool, Online XSLT 2.0 Service, provided by W3C. Instructions for this process can be found in Appendix 4.
The stylesheet has also been tested using oXygen version 12.2, whereby it was confirmed that all examples in the directory http://ruleml.org/1.0/exa are properly upgraded. However, the upgraded instances documents will have the RuleML namespace as the default namespace, independent of the choice of prefix for the RuleML namespace in the original instance. A similar 091-to-ruleml100.xslt has been developed that uses the prefix "ruleml" for the RuleML namespace.
An XSLT processor which may be used to perform these transformations on a whole directory at once is Saxon, using the following command:
$ java net.sf.saxon.Transform -o 1.0/exa/ 0.91/exa/ 091-to-100.xslt
A use example of the Upgrader is described in the WineOnto migration path documentation.
RuleML has always allowed abbreviated encoding (skipped edge tags and default attribute values) and some freedom in the ordering of elements. The new Relax NG schemas allows even more freedom in element ordering than the XSD schemas, with all perturbations possible as long as the missing edge tags may be unambiguously reconstructed. An XSLT stylesheet has been developed (see RON, also see the Normalizer directory) for normalizing the syntax used in a given RuleML Version 1.0 instance, undoing the abbreviated encoding and re-ordering of elements. An example of the normal form is the expanded version of the compact 'own' example.
The goals of this normalizer include the following:
We say that using this normalizer followed by schema-based RuleML validation performs "normalidation" on RuleML instances. That is to say, not only are missing edge tags and attributes with default values inserted into the RuleML Version 1.0 instance in order to normalize it, but the general tree structure of the file is also validated syntactically to ensure that Node and edge elements only appear in correct positions.
The following is a list of the operations the RuleML Version 1.0 XSLT Normalizer should perform whenever it is used on an XML instance. Note that the Normalizer is intended to successfully transform XML instances that may not be valid RuleML Version 1.0 (validation is the second step of the "Normalidation" process); therefore no assumptions are made about the names or number of child elements in the instance being transformed.<Implies>, <Entails>
<if>-<then> edge elements are both missing, wrap the first "naked Node" (a Node element that
has a Node parent element) child within an <if> edge element, and the second naked Node child within a <then> edge element.
<if>-<then> edge elements is missing, wraps the first naked RuleML Node element within the missing edge element.
<oid>, then
<if>, followed by
<then>, followed by any other children.
<Expr>
<Fun> child (if any) with an <op> edge element.
<arg> edge elements (with an index attribute) wrapping each remaining naked RuleML Node (if any). The naked Node children that may occur within this element in a valid
RuleML Version 1.0 instance include:
<Ind>,
<Var>,
<Fun>,
<Plex>,
<Reify>,
<Data>, or
<Skolem>.
<oid>, followed by
<op>, followed by
positional arguemnts (<arg>, then
<repo>)
followed by
slotted arguemnts (<slot>, then
<resl>), followed by
any other children.
<Atom>
<Rel> child (if any) with an <op>.
<arg> edge elements (with an index attribute) wrapping each naked Node.
The naked Node children that may occur within this element in a valid RuleML Version 1.0 instance include:
<Ind>,
<Var>,
<Fun>,
<Plex>,
<Reify>,
<Data>, or
<Skolem>.
<oid>, followed by
<degree>, followed by
<op>, followed by
positional arguemnts (<arg>, then
<repo>) followed by
slotted arguemnts (<slot>, then
<resl>), followed by
any other children.
<Uniterm>
<op> element, wrap the first child that is not
<oid> or
<degree>
within a <op> element.
<arg> edge elements (with an index attribute) to each of the remaining naked child Nodes.
The naked Node children that may occur within this element in a valid RuleML Version 1.0 instance include:
<Const>,
<Var>,
<Reify>,
<Uniterm>,
<Skolem>.
<oid>, followed by
<degree>, followed by
<op>, followed by
positional arguemnts (<arg>, then
<repo>, followed by
slotted arguemnts (<slot>, then
<resl>), followed by
any other children.
<Assert>,
<Retract>,
<Query>,
<And>,
<Or>
<formula> edge element.
<Forall>, <Exists>
<RuleML>
<Neg>
<Naf>
<Equivalent>
<Equal>
<left> element and second naked Node child with <right> element.
<left> edge element, and the second child has no <left> or <right> edge element, the XSLT will wrap the second child with the <right> edge element.
<oid>, followed by
<degree>, followed by
<left>, followed by
<right>, followed by
any other children.
For example, the compact version of the 'own' example:
<RuleML>
<Assert mapClosure="universal">
<Implies>
<And>
<Atom>
<Rel>buy</Rel>
<Var>person</Var>
<Var>merchant</Var>
<Var>object</Var>
</Atom>
<Atom>
<Var>person</Var>
<Rel>keep</Rel>
<Var>object</Var>
</Atom>
</And>
<Atom>
<Var>person</Var>
<Rel>own</Rel>
<Var>object</Var>
</Atom>
</Implies>
...
<Atom>
<Ind>Mary</Ind>
<Rel>keep</Rel>
<Ind>XMLBible</Ind>
</Atom>
</Assert>
</RuleML>
|
should be normalized to the expanded version:
<RuleML>
<act index="1">
<Assert mapClosure="universal">
<formula>
<Implies>
<if>
<And>
<formula>
<Atom>
<op><Rel>buy</Rel></op>
<arg index="1"><Var>person</Var></arg>
<arg index="2"><Var>merchant</Var> </arg>
<arg index="3"><Var>object</Var></arg>
</Atom>
</formula>
<formula>
<Atom>
<op><Rel>keep</Rel></op>
<arg index="1"><Var>person</Var></arg>
<arg index="2"><Var>object</Var></arg>
</Atom>
</formula>
</And>
</if>
<then>
<Atom>
<op><Rel>own</Rel></op>
<arg index="1"><Var>person</Var></arg>
<arg index="2"><Var>object</Var></arg>
</Atom>
</then>
</Implies>
</formula>
...
<formula>
<Atom>
<op><Rel>keep</Rel></op>
<arg index="1"><Ind>Mary</Ind></arg>
<arg index="2"><Ind>XMLBible</Ind></arg>
</Atom>
</formula>
</Assert>
</act>
</RuleML> |
XSLT processing will be accomplished using procedures identical to those of the XSLT Upgrader. Instructions for the W3C web-based process can be found in Appendix 4.
The Glossary for RuleML Version 1.0 contains descriptions for every element in RuleML Version 1.0.
As in previous versions of RuleML, there are several pairs of attributes in RuleML Version 1.0 that have names which differ only by a 'map' prefix: @closure and @mapClosure, @direction and @mapDirection, and @material and @mapMaterial. The naming convention reflects attribute 'mapping' through XML trees, where
<NodeName mapAttribute="..."><C1>. . .</C1>. . .<CN>. . .</CN></NodeName>
basically acts like
<NodeName><NodeChildName1 attribute="...">. . .</NodeChildName1>. . .<NodeChildNameN attribute="...">. . .</NodeChildNameN></NodeName>
or
<NodeName><edgeName1><NodeChildName1 attribute="...">. . .</NodeChildName1></edgeName1>. . .<edgeNameN><NodeChildNameN attribute="...">. . .</NodeChildNameN></edgeNameN></NodeName>
The XSD schemas use a tree-based modularization strategy. The most current model of the XSD modularization of RuleML is always documented at http://ruleml.org/modularization/#Model.
The Relax NG schemas use a different modularization approach based on lattices. The details are given in the publication about the re-engineering of RuleML in Relax NG and the RuleML MYNG Wiki page. MYNG is accessible through a GUI or, for advanced users, a PHP script .
The XSD Schemas specification of RuleML Version 1.0 has been created using an approach that is consistent with that of all earlier XSDs, and back to that of the (version 0.85) DTDs. The Content Models document should be read in parallel to the XSD schemas, because they give a high-level, complete documentation of the XSDs. Likewise, the Glossary can help to find quick descriptions of, and cross-reference between, the RuleML Version 1.0 XML elements.
Appended below is a simple example rulebase (Appendix 1), the XSD Schema for the Datalog sublanguage of RuleML to which the rulebase conforms (Appendix 2), instructions for how to validate instances against the XSD schema (Appendix 3), instructions for how to transform with XSLT stylesheets (Appendix 4), and instructions for how to validate instances against the Relax NG schema (Appendix 5).
Source: own-xsd.ruleml
<?xml version="1.0" encoding="UTF-8"?>
<RuleML
xmlns="http://ruleml.org/spec"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ruleml.org/spec http://ruleml.org/1.0/xsd/datalog.xsd"
>
<Assert mapClosure="universal">
<!-- start XML comment ...
This example rulebase contains four rules.
The first and second rules are implications; the third and fourth ones are facts.
In English:
The first rule implies that a person owns an object
if that person buys the object from a merchant and the person keeps the object.
As an OrdLab Tree:
Implies~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* *
if * then *
* *
And~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Atom~~~~~~~~~~~~~~~~~~
| | * | |
| | op * | |
| | * | |
Atom~~~~~~~~~~~~~~~~~~~~~~~~~~~ Atom~~~~~~~~~~~~~~~~~~ Rel Var Var
* | | | * | | . . .
op * | | | op * | | . . .
* | | | * | | . . .
Rel Var Var Var Rel Var Var own person object
. . . . . . .
. . . . . . .
. . . . . . .
buy person merchant object keep person object
... end XML comment -->
<Implies>
<if>
<!-- explicit 'And' -->
<And>
<Atom>
<op><Rel>buy</Rel></op>
<Var>person</Var>
<Var>merchant</Var>
<Var>object</Var>
</Atom>
<Atom>
<op><Rel>keep</Rel></op>
<Var>person</Var>
<Var>object</Var>
</Atom>
</And>
</if>
<then>
<Atom>
<op><Rel>own</Rel></op>
<Var>person</Var>
<Var>object</Var>
</Atom>
</then>
</Implies>
<!-- The second rule implies that a person buys an object from a merchant
if the merchant sells the object to the person. -->
<Implies>
<if>
<Atom>
<op><Rel>sell</Rel></op>
<Var>merchant</Var>
<Var>person</Var>
<Var>object</Var>
</Atom>
</if>
<then>
<Atom>
<op><Rel>buy</Rel></op>
<Var>person</Var>
<Var>merchant</Var>
<Var>object</Var>
</Atom>
</then>
</Implies>
<!-- The third rule is a fact that asserts that
John sells XMLBible to Mary. -->
<Atom>
<op><Rel>sell</Rel></op>
<Ind>John</Ind>
<Ind>Mary</Ind>
<Ind>XMLBible</Ind>
</Atom>
<!-- The fourth rule is a fact that asserts that
Mary keeps XMLBible.
Observe that this fact is binary - i.e., there are two arguments
for the relation. RDF viewed as a logical knowledge representation
is, likewise, binary, although its arguments have type restrictions,
e.g., the first must be a resource (basically, a URI). -->
<Atom>
<op><Rel>keep</Rel></op>
<Ind>Mary</Ind>
<Ind>XMLBible</Ind>
</Atom>
</Assert>
</RuleML> |
Source: datalog.xsd
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns="http://ruleml.org/spec" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://ruleml.org/spec" > <xs:annotation> <xs:documentation xml:lang="en"> XML Schema for the RuleML sublanguage "datalog". File: datalog.xsd Version: 1.0 Last Modification: 2010-07-16 </xs:documentation> </xs:annotation> <!-- Note that datalog is entirely composed of modules and that all other schema drivers rely on it, making it the root of the sublanguage family tree. --> <!-- Datalog includes the following modules: * performative * desc * quantifier * connective * atom * slot * term * uri For details on each module, including what element and/or attribute declarations they contain, please refer to them individually. --> <xs:include schemaLocation="modules/performative_module.xsd"/> <xs:include schemaLocation="modules/desc_module.xsd"/> <xs:include schemaLocation="modules/quantifier_module.xsd"/> <xs:include schemaLocation="modules/connective_module.xsd"/> <xs:include schemaLocation="modules/atom_module.xsd"/> <xs:include schemaLocation="modules/slot_module.xsd"/> <xs:include schemaLocation="modules/term_module.xsd"/> <xs:include schemaLocation="modules/uri_module.xsd"/> </xs:schema> |
You should get the following output (using the default output):
http://ruleml.org/1.0/exa/Datalog-xsd/own-xsd.ruleml{http://ruleml.org/spec}RuleML{http://ruleml.org/spec}:RuleML.typeAttempt to load a schema document from
http://ruleml.org/1.0/xsd/datalog.xsd
(source: schemaLoc) for
http://ruleml.org/spec,
succeeded
Attempt to load a schema document from
http://ruleml.org/1.0/xsd/modules/performative_module.xsd
(source: include) for
http://ruleml.org/spec,
succeeded
Attempt to load a schema document from
http://ruleml.org/1.0/xsd/modules/desc_module.xsd
(source: include) for
http://ruleml.org/spec,
succeeded
Attempt to load a schema document from
http://ruleml.org/1.0/xsd/modules/quantifier_module.xsd
(source: include) for
http://ruleml.org/spec,
succeeded
Attempt to load a schema document from
http://ruleml.org/1.0/xsd/modules/connective_module.xsd
(source: include) for
http://ruleml.org/spec,
succeeded
Attempt to load a schema document from
http://ruleml.org/1.0/xsd/modules/atom_module.xsd
(source: include) for
http://ruleml.org/spec,
succeeded
Attempt to load a schema document from
http://ruleml.org/1.0/xsd/modules/slot_module.xsd
(source: include) for
http://ruleml.org/spec,
succeeded
Attempt to load a schema document from
http://ruleml.org/1.0/xsd/modules/term_module.xsd
(source: include) for
http://ruleml.org/spec,
succeeded
Attempt to load a schema document from
http://ruleml.org/1.0/xsd/modules/iri_module.xsd
(source: include) for
http://ruleml.org/spec,
succeeded
Changes in the RuleML Version 1.0 XSD release relative to the previous XSD version 0.91 are detailed below, including examples where appropriate.
The terminology "Type" and "role" (when referring to XML tags or elements) has been changed to "Node" and "edge", in order to avoid the confusion caused by simultaneous usage of multiple meanings of these words, as well as to emphasize the connection to graphs, especially the RDF graph model.
Schematron dependency has been reduced (as comments in the code). For example, the following code provides annotation related to restrictions on the interpretation attribute of nested functions.
<xs:annotation>
<xs:appinfo>
<sch:pattern name="Uninterpreted functions">
<sch:rule context="r:Expr/r:Fun[@per='no']">
<sch:assert test=
"not(../r:Expr/r:Fun[@per='yes'] or
../r:arg/r:Expr/r:Fun[@per='yes'] or
../r:Expr/r:op/r:Fun[@per='yes'] or
../r:arg/r:Expr/r:op/r:Fun[@per='yes'])">
Functions nested within an uninterpreted function must also be uninterpreted.
</sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation> |
Edge elements <head> and <body> are replaced with <then> and <if>, respectively.
These elements appear as children of <Implies> and <Entails>.
For example, the following implication:
<Implies>
<if>
<And>
<Atom>
<Rel>premium</Rel>
<Var>cust</Var>
</Atom>
<Atom>
<Rel>regular</Rel>
<Var>prod</Var>
</Atom>
</And>
</if>
<then>
<Atom>
<Rel>discount</Rel>
<Var>cust</Var>
<Var>prod</Var>
<Data>5.0 percent</Data>
</Atom>
</then>
</Implies> |
expresses the statement "A premium customer recieves a 5% discount on regular products."
Edge elements <lhs> and
<rhs>
are replaced with <left>
and <right>, respectively.
These elements appear as children of <Equal>.
As an example consider the statement:
<Equal>
<left>
<Ind>Lady Gaga</Ind>
</left>
<right>
<Ind>Stefani Joanne Angelina Germanotta</Ind>
</right>
</Equal> |
which expresses that the individuals named "Lady Gaga" and "Stefani Joanne Angelina Germanotta" are the same.
In the SWSL languages, which are implemented only in the XSDs, Node elements
<Hterm> and
<Con> are replaced with
<Uniterm> and
<Const> respectively.
Attribute @in="no|semi|yes" with respective values are
replaced with @per="copy|open|value".
For example, the following functional expression uses the default value ("copy") of
the attribute "per"
<Expr per="copy"> <op><Fun>MultiplyFn</Fun></op> <arg index="1"><Data xsi:type="xs:integer">3</Data></arg> <arg index="2"><Var>X</Var></arg> </Expr> |
to generate an algebraic expression that may be evaluated after the variable X is bound to a numerical value. In contrast, the expression
<Expr per="value"> <op><Fun>MultiplyFn</Fun></op> <arg index="1"><Data xsi:type="xs:integer">3</Data></arg> <arg index="2"><Data xsi:type="xs:integer">4</Data></arg> </Expr> |
will be evaluated (to <Data xsi:type="xs:integer">12</Data>)
before inference is performed.
Attribute @uri is replaced with
@iri.
This attribute is used to identify, by Internationalized Resource Identifier (IRI),
the elements <Ind>,
<Rel> and
<Fun> as individuals,
relations and functions, respectively. For example:
<Atom>
<op>
<Rel iri="http://dublincore.org/documents/dces/index.shtml.rdf#Creator"/>
</op>
<Ind iri="http://www.w3.org/Home/Lassila"/>
<Data xsi:type="xs:string">Ora Lassila</Data>
</Atom> |
expresses a fact equivalent to the RDF triple:
<rdf:RDF xmlns:s="http://dublincore.org/documents/dces/index.shtml.rdf">
<rdf:Description about="http://www.w3.org/Home/Lassila">
<s:Creator>Ora Lassila</s:Creator>
</rdf:Description>
</rdf:RDF> |
A new edge element <act>,
with a required @index attribute,
is introduced as an optional wrapper for all performatives of the <RuleML> element,
as shown here:
<RuleML>
<act index="1">
<Assert/>
</act>
</RuleML> |
Additional freedom in element order with partial stripe-skipping has been introduced
in the "relaxed form serialization", as specified in the Relax NG schemas.
In particular, infix and postfix operator notation is now allowed in the relaxed form
serialization as long as the <op> element is not skipped.
Features that are "deprecation candidates", i.e. that may be deprecated in future releases, include:
<Reify> at Datalog and lower, as this introduces the possibility of nesting reification to
an arbitrary level ;
@direction,
@mapDirection,
@material,
@mapMaterial,
@oriented,
@val,
@per, as it may be more effective to use the absence of the attribute to indicate a "neutral"
semantics;
<oid> as a child of Nodes other than <Atom> or certain cases of <Expr> and <Uniterm> does not have commonly accepted semantics (in particular, F-logic's object semantics,
as adapted in W3C RIF and developed in PSOA RuleML), although it has been informally
used in earlier RuleML instances for labels, which sometimes have consisted of entire comment lines (RuleML Version 1.0 instances use XML-level comments instead, while a future RuleML version is expected to introduce/adopt a metadata mechanism.)
During the review of the RuleML Version 0.91 XSD schemas that was conducted in conjunction with the re-engineering of RuleML in Relax NG, a number of shortcomings and defects were identified. A number of these issues were patched in the Version 0.91 Patched release, and these patched XSDs form the basis of the hand-written XSDs for RuleML Version 1.0. There are several issues that could not be resolved in the handwritten XSDs, including:
<Reify>). For example, in bindatagroundfact, it is valid to reify a universal quantification
(<Forall>
), while it is not allowed to construct a universal quantification in the language.
It is not possibly to fix this issue without discarding the tree-based modularization
approach of the hand-written schemas. Because RuleML Version 1.0 is a "Rosetta" release, we have retained the hand-written XSD schemas that contain this issue for consistency with legacy schemas. However, the
Relax NG schemas are not affected by this issue, and thus there is a discrepancy between
the XSD and Relax NG schemas in these unusual cases.
Site Contact:
Tara Athan.
Page Version: 2012-01-28
"Practice what you preach": XML source of this homepage at index.xml;
transformed to HTML via the adaptation of Michael Sintek's SliML XSLT stylesheet at homepage.xsl (View | Page Source)