RELAX NG by Eric van der Vlist will be published by O'Reilly & Associates (ISBN: 0596004214)
You are welcome to use our annotation system to give your feedback.
After this long introduction to annotation syntax, it is time to explore applications of annotations. The first application of annotations is for documentation. The issue of generating documentation from schemas, much like the problem of generating documentation from code, is a long running problem with three different schools of thought:
The documentation and the schema are stored separately. In this case there is nothing specific to documenting RELAX NG schemas and this is beyond the scope of this book.
The schema can be embedded in the documentation: proponents of "Literate Programming" are fans of this approach. It will be presented in our next chapter, Chapter 14: Generating RELAX NG schemas.
The documentation can be embedded within the schema: this approach is what we'll cover in this section.
We've seen the technical basis of how these annotations may be included in RELAX NG schemas. Generating documentation from these annotations is mainly a matter of writing an XSLT transformation to extract them, and then format the annotations according to your needs. We won't be going through the details of XSLT transformations, but the following examples would be good candidates for these kinds of transformation.
This example uses simple comments:
<define name="author-element"> <!-- Definition of the author element --> <element name="author"> <attribute name="id"/> <ref name="name-element"/> <ref name="born-element"/> <optional> <ref name="died-element"/> </optional> </element> </define> |
which is equivalent to:
author-element = # Definition of the author element element author { attribute id { text }, name-element, born-element, died-element? } |
These comments can be easily extracted, not only from the XML syntax using a n XSLT transformation, but also from the compact syntax using regular expressions.
Comments provide a lightweight way to document RELAX NG schemas. They are the least intrusive mechanism to annotate schemas and can be used at any location in a schema, even within the text only patterns value and param.
The downsides of comments are well known:
The XML recommendation states that parsers don't have to report them, so some tools just ignore them. This was the case for early parsers and editors, but the situation has improved since the early days of XML. Most, if not all, of the XML parsers and editors now report XML comments.
Comments may only contain plain text and have no XML structures. In the context of a RELAX NG schema, this is often not a concern; however, when needed, conventions can easily be added to define specific structures. This is done in JavaDoc, for example, where special "tags" are prefixed by @. Similarly, Wiki Wiki Webs express links as "[ link title|http://...link.location]".
We have already mentioned the RELAX NG DTD Compatibility specification in our chapter about external datatype libraries in Chapter 8: Datatype Libraries where we studied the DTD datatypes. RELAX NG includes more than datatypes in the compatibility specification. It also includes a way to specify comments which would appear in a DTD equivalent to the RELAX NG schema. It also specifies an annotation for defining default values, which will be covered later on in this chapter.
DTD compatibility comments have a special status: the RELAX NG Technical Committee has defined a namespace for them and provided a shortcut to provide a concise form in the compact syntax. As annotations in the XML syntax and comment like in the compact syntax, they are thus a kind of middle ground between XML comments and RELAX NG annotations.
When using the XML syntax, DTD Compatibility Comments are foreign elements in the namespace http://relaxng.org/ns/compatibility/annotations/1.0. Their content is text-only and they may be annotated using foreign namespace attributes. An example of schema using this feature is:
<?xml version="1.0" encoding="utf-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"> <a:documentation>RELAX NG flat schema for our library</a:documentation> <start> <element name="library"> <oneOrMore> <ref name="book-element"/> </oneOrMore> </element> </start> <define name="author-element"> <a:documentation>Definition of the author element</a:documentation> <element name="author"> <attribute name="id"/> <ref name="name-element"/> <ref name="born-element"/> <optional> <ref name="died-element"/> </optional> </element> </define> .../... </grammar> |
An equivalent schema using the compact syntax is:
## RELAX NG flat schema for our library grammar{ start = element library { book-element+ } ## Definition of the author element author-element = element author { attribute id { text }, name-element, born-element, died-element? } .../... } |
Note that the syntax with the leading double hashes ( ##) are analogous to the /** comments used in JavaDoc. Despite the fact that they they look like comments, these are annotations that have the same meaning and rules as initial annotations. They must precede the pattern to which they apply. This form is equivalent to:
namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" [[ a:documentation [ "RELAX NG flat schema for our library" ] ] grammar { start = element library { book-element+ } [[ a:documentation [ "Definition of the author element" ] ] author-element = element author { attribute id { text }, name-element, born-element, died-element? } ../.. } |
This shortcut has the same restrictions as initial annotations in that they must precede all the initial annotations. It is possible to mix them with other types of annotations and write, for instance:
namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" a:documentation [ "RELAX NG flat schema for our library" ] start = element library { book-element+ } ## Definition of the author element author-element = element author { attribute id { text }, name-element, born-element, died-element? } .../... |
Up to now, we have seen examples of compatibility comments that were the first child element in their parent. This has hidden an important feature of these comments: they are using the trick we mentioned in the previous section about workarounds for annotating param and value patterns. They apply their comments to the preceding sibling from the RELAX NG namespace when there is one. If we want to annotate the reference to the name-element definition, we can either write:
<define name="author-element"> <element name="author"> <attribute name="id"/> <ref name="name-element"> <a:documentation>Definition of the author element</a:documentation> </ref> <ref name="born-element"/> <optional> <ref name="died-element"/> </optional> </element> </define> |
or:
<define name="author-element"> <element name="author"> <attribute name="id"/> <ref name="name-element"/> <a:documentation>Definition of the author element</a:documentation> <ref name="born-element"/> <optional> <ref name="died-element"/> </optional> </element> </define> |
In the first case, the DTD compatibility annotation is the first child element of its parent element (ref) and applies to the ref pattern for this reason. In the second case, the annotation is not the first child element from the RELAX NG namespace and applies to his preceding sibling, which is the ref pattern again.
The compact syntax has the same rules, so the following annotations are equivalent:
author-element = element author { attribute id { text }, ## Definition of the author element name-element, born-element, died-element? } |
and:
author-element = element author { attribute id { text }, name-element >> a:documentation [ "Definition of the author element" ], born-element, died-element? } |
Here again, a following annotation is considered as an annotation of the name-element reference.
Of course, if we were annotating a param or value pattern we would have no other choice than to locate the annotation after the pattern and this is why this tricky mechanism has been introduced.
XHTML seems like a natural choice for embedding documentation in RELAX NG schemas. We have already seen several examples of such annotations. The main benefit of XHTML is that it is so similar to HTML that it is known by pretty much anyone who has ever published a web page. A lot of documentation and books are available on XHTML and many editors can be used to edit XHTML documents. Furthermore, if you keep to a reasonable subset of XHTML (such as for instance XHTML Basic), you have a simple and generic language to use for writing documentation. The work needed if you want to publish the result of the extraction of XHTML annotations as HTML is minimal since your annotations are already XHTML.
You will find more information about XHTML at the W3C web site: http://www.w3.org/MarkUp/ as well as in specialized books such as "HTML & XHTML: The Definitive Guide" (O'Reilly 2002) and "XHTML: Moving Toward XML" (M&T Books 2000).
We have also seen many examples of XHTML annotations, such as:
<?xml version="1.0" encoding="utf-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <xhtml:div> <xhtml:h1>RELAX NG flat schema for our library</xhtml:h1> <xhtml:p>This schema has been written by <xhtml:a href="http://dyomedea.com/vdv">Eric van der Vlist</xhtml:a>.</xhtml:p> </xhtml:div> .../... </grammar> |
or, using the compact syntax:
namespace xhtml = "http://www.w3.org/1999/xhtml" xhtml:div [[ xhtml:h1 [ "RELAX NG flat schema for our library" ] xhtml:p [[ "This schema has been written by " xhtml:a [ href = "http://dyomedea.com/vdv" "Eric van der Vlist" ] "." ] ] start = element library { book-element+ } .../... |
Beyond the syntax which has already been discussed in the first part of this chapter, note how we have embedded a title ( xhtml:h1) and a paragraph (xhtml:p) within a division ( xhtml:div). This is generally a good practice which makes it easier to associate the title with the rest of the content and to manipulate the annotation as a whole.
First designed as an SGML application and very popular for writing technical documentation, DocBook is now also an XML language. With more features than XHTML, DocBook offers many predefined bells and whistles to facilitate indexes and cross references. DocBook makes it easy to indicate that some bit of text is a snippet of source code, it can identify acronyms, and many other things. These features can be emulated in XHTML using the class attribute, but in DocBook they are built-in from the beginning and there is a common meaning.
You will find more information about DocBook on its web site: http://www.oasis-open.org/committees/docbook/ and in the book "DocBook: The Definitive Guide" (O'Reilly).
DocBook is defined as a DTD which doesn't use any namespaces. That's not an issue, as RELAX NG allows annotations through elements without namespace. To give you an idea of what DocBook looks like as well as an example showing how to "undeclare" a namespace in XML, the following example would more or less match what we had written in XHTML in the previous one:
<?xml version="1.0" encoding="utf-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0"> <sect1 xmlns=""> <title>RELAX NG flat schema for our library</title> <para>This schema has been written by <xref linkend="vdv"/>.</para> </sect1> <start> <element name="library"> <oneOrMore> <ref name="book-element"/> </oneOrMore> </element> </start> .../... </grammar> |
Or, with the compact syntax:
sect1 [[ title [ "RELAX NG flat schema for our library" ] para [[ "This schema has been written by " xref [ linkend = "vdv" ] "." ] ] start = element library { book-element+ } .../... |
While XHTML and DocBook are great for including content as documentation, Dublin Core fills a different niche. It is widely used over the web to include metadata about all type of resources. Dublin Core includes a set of elements with a description of their semantics. This provides sharable information including details relevant to a schema. Dublin Core can answer questions about the schema's authors, their organization, the date, or the copyright associated with the schema. Dublin Core is very complementary to DocBook and XHTML and is often used in XHTML documents where it finds a natural fit in the meta element.
Note | |
---|---|
You will find more information about Dublin Core on their site: http://dublincore.org/ . |
In a RELAX NG schema, Dublin Core elements may be included wherever it makes sense. Under the grammar pattern, they will qualify the whole grammar while under an element pattern, they would be useful to qualify the specific element.
A more complete example than those shown previously includes, title, creator, subject, description, date, language, and rights information for a schema:
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://relaxng.org/ns/structure/1.0"> <dc:title>The library element</dc:title> <dc:creator>Eric van der Vlist</dc:creator> <dc:subject>library, book, RELAX NG</dc:subject> <dc:description>This RELAX NG schema has been written as an example to show how Dublin Core elements may be used.</dc:description> <dc:date>2003-01-30</dc:date> <dc:language>en</dc:language> <dc:rights>Copyright Eric van der Vlist, Dyomedea. During development, I give permission for non-commercial copying for educational and review purposes. After publication, all text will be released under the Free Software Foundation GFDL.</dc:rights> .../... </grammar> |
or:
namespace dc = "http://purl.org/dc/elements/1.1/" dc:title [ "The library element" ] dc:creator [ "Eric van der Vlist" ] dc:subject [ "library, book, RELAX NG" ] dc:description [ "This RELAX NG schema has been written as an example to show how Dublin Core elements may be used." ] dc:date [ "2003-01-30" ] dc:language [ "en" ] dc:rights [ "Copyright Eric van der Vlist, Dyomedea. \x{a}" ~ " During development, I give permission for non-commercial copying for \x{a}" ~ " educational and review purposes. \x{a}" ~ " After publication, all text will be released under the \x{a}" ~ " Free Software Foundation GFDL." ] .../... |
There is no reason to limit ourselves to text and metadata - graphics can be included too, thanks to Scalable Vector Graphics (SVG). SVG is an XML vocabulary published by the W3C, and can be integrated as RELAX NG annotations like any other XML vocabulary:
<?xml version="1.0" encoding="utf-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:svg="http://www.w3.org/2000/svg"> <start> <element name="library"> <oneOrMore> <ref name="book-element"/> </oneOrMore> </element> </start> <define name="author-element"> <element name="author"> <svg:svg> <svg:title>A typical author</svg:title> <svg:ellipse style="stroke:#000000; fill:#e3e000; stroke-width:2pt;" id="head" cx="280" cy="250" rx="110" ry="130"/> <svg:ellipse style="stroke:none; fill:#7f7f7f; " id="leftEye" cx="240" cy="225" rx="18" ry="18"/> <svg:ellipse style="stroke:none; fill:#7f7f7f; " id="rightEye" cx="320" cy="225" rx="18" ry="18"/> <svg:path style="fill:none;stroke:#7F7F7F; stroke-width:5pt;" id="mouth" d="M 222 280 A 58 48 0 0 0 338 280"/> </svg:svg> <attribute name="id"/> <ref name="name-element"/> <ref name="born-element"/> <optional> <ref name="died-element"/> </optional> </element> </define> .../... </grammar> |
Or, using the compact syntax:
namespace svg = "http://www.w3.org/2000/svg" |
start = element library { book-element+ } author-element = [[ svg:svg [[ svg:title [ "A typical author" ] svg:ellipse >[ style = "stroke:#000000; fill:#e3e000; stroke-width:2pt;" id = "head" cx = "280" cy = "250" rx = "110" ry = "130" ] svg:ellipse [ style = "stroke:none; fill:#7f7f7f; " id = "leftEye" cx = "240" cy = "225" rx = "18" ry = "18" ] svg:ellipse [ style = "stroke:none; fill:#7f7f7f; " id = "rightEye" cx = "320" cy = "225" rx = "18" ry = "18" ] svg:path [ style = "fill:none;stroke:#7F7F7F; stroke-width:5pt;" id = "mouth" d = "M 222 280 A 58 48 0 0 0 338 280" ] ] ] element author { attribute id { text }, name-element, born-element, died-element? } .../... |
I leave it to you as an additional exercise to visualize what a typical author looks like!
Note | |
---|---|
You will find more information about SVG on its web site: http://www.w3.org/Graphics/SVG/ as well as in the book book "SVG Essentials" (O'Reilly, 2002). |
The last type of annotation I'd like to mention provides a transition between annotations for documentation purposes and annotation for applications. RDDL has been designed as an XML vocabulary which can be used by humans as documentation and by applications. Although RDDL was invented to document namespaces, it found a very good fit in a RELAX NG schema. The informationprovided by RDDL annotations can be extracted to constitute RDDL documentation for the namespaces described in the schema. RDDL is based on XHTML and XLink and also works well with XHTML documentation.
Note | |
---|---|
You will find more information about RDDL on its web site: http://rddl.org . |
The main benefit of RDDL is that it provides a way to associate resources with a document. As an example, let's use it to associate an XSLT template and a CSS style sheet with the definition of the author element:
<?xml version="1.0" encoding="utf-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rddl="http://www.rddl.org/" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <start> <element name="library"> <oneOrMore> <ref name="book-element"/> </oneOrMore> </element> </start> <define name="author-element"> <element name="author"> <xhtml:div> <rddl:resource id="author-transform" xlink:arcrole="http://www.w3.org/1999/xhtml" xlink:role="http://www.w3.org/1999/XSL/Transform" xlink:title="Author XSLT template" xlink:href="library.xslt#author"> <xhtml:div class="resource"> <xhtml:h4>XSLT Transformation</xhtml:h4> <xhtml:p>This <xhtml:a href="library.xslt#author">XSLT template</xhtml:a> displays the description of an author as XHTML.</xhtml:p> </xhtml:div> </rddl:resource> <rddl:resource id="CSS" xlink:title="CSS Stylesheet" xlink:role="http://www.isi.edu/in-notes/iana/assignments/media-types/text/css" xlink:href="author.css"> <xhtml:div class="resource"> <xhtml:h4>CSS Stylesheet</xhtml:h4> <xhtml:p>A <xhtml:a href="author.css">CSS stylesheet</xhtml:a> defining some cool styles to display an author.</xhtml:p> </xhtml:div> </rddl:resource> </xhtml:div> <attribute name="id"/> <ref name="name-element"/> <ref name="born-element"/> <optional> <ref name="died-element"/> </optional> </element> </define> .../... </grammar> |
or:
namespace rddl = "http://www.rddl.org/" namespace xhtml = "http://www.w3.org/1999/xhtml" namespace xlink = "http://www.w3.org/1999/xlink" start = element library { book-element+ } author-element = [[ xhtml:div [[ rddl:resource [[ id = "author-transform" xlink:arcrole = "http://www.w3.org/1999/xhtml" xlink:role = "http://www.w3.org/1999/XSL/Transform" xlink:title = "Author XSLT template" xlink:href = "library.xslt#author" xhtml:div [[ class = "resource" xhtml:h4 [ "XSLT Transformation" ] xhtml:p [[ "This " xhtml:a [ href = "library.xslt#author" "XSLT template" ] " displays the description of an author as XHTML." ] ] ] rddl:resource [[ id = "CSS" xlink:title = "CSS Stylesheet" xlink:role = "http://www.isi.edu/in-notes/iana/assignments/media-types/text/css" xlink:href = "author.css" xhtml:div [[ class = "resource" xhtml:h4 [ "CSS Stylesheet" ] xhtml:p [[ xhtml:a [ href = "author.css" "CSS stylesheet" ] " defining some cool styles to display an author." ] ] ] ] ] element author { attribute id { text }, name-element, born-element, died-element? } .../... |
Applications which understand RDDL can act on this information automatically, while humans can find it through the XHTML documentation included with it.
You are welcome to use our annotation system to give your feedback.
[Annotations for this page]
All text is copyright Eric van der Vlist, Dyomedea. During development, I give permission for non-commercial copying for educational and review purposes. After publication, all text will be released under the Free Software Foundation GFDL.