XForms, XML Schema, and ROX
by Kurt Cagle
|
Pages: 1, 2, 3
The specific transformations to generate the metastructure patterns for each element were done using an XSLT2 template (specifically Saxon 8.9, though there is no specific Saxon code utilized. One underlying assumption in the transformation was that the schema must be defined as an Element Nominal Schema (the author's notation). Such a schema assumes that there are only a limited number (preferably only one) of high-level element declarations, and each declaration in turn points to a Complex Type that holds the child elements:
<xs:schema ...>
<xs:element name="toplevel" type="toplevel.Type"/>
<xs:complexType name="toplevel.Type">
<xs:sequence>
<xs:element name="sublevelA" type="sublevelA.Type"/>
<xs:element name="sublevelB" type="sublevelB.Type"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sublevelA.Type">
...
</xs:complexType>
<xs:complexType name="sublevelB.Type">
...
</xs:complexType>
...
</xs:schema>
Note that in this particular format, most of the content of the schema should be either simple or complex type declarations and child elements are defined specifically by name (thus Element Nominal), rather than containing a reference to another element declaration block elsewhere in the schema. Moreover, in this particular example (and in the examples used in ROX in general) the use of anonymous type declarations, where an element contains an encoding complex type element that isn't named, is discouraged.
The transformations themselves are reasonably complex, and, as such ,are best reviewed offline; check out the references at the end of this article for the set of code used in this application, including XSLT transformations and XQueries. Once the transformation is done, however, it creates a one-to-one mapping between each element in the schema and its corresponding matched template that describes the element's namespace, CSS overlays, constraints, labels and so forth. The results of this (in the particular case for a CV schema) looks as follows for a portion of the metastructure document:
<structure lang="us-en" root-match="cv:CV"
namespace="http://www.casrai.org/xmlns/2007/cv"
namespace-prefix="cv">
...
<element match="cv:Book">
<title>Book</title>
<display-title>yes</display-title>
<type>cv:Book.Type</type>
<core-type>complexType</core-type>
<metadata>Record</metadata>
<propertysheet>
<property label="Title Of Work"
select="cv:TitleOfWork"/>
<property label="Co Authors"
select="cv:CoAuthors"/>
<property label="Publisher"
select="cv:Publisher"/>
<property label="Published Work Status"
select="cv:PublishedWorkStatus"/>
<property label="Number Of Pages"
select="cv:NumberOfPages"/>
<property label="Publication Location"
select="cv:PublicationLocation"/>
<property label="Publication Year"
select="cv:PublicationYear"/>
<property label="Edition"
select="cv:Edition"/>
<property label="Number Of Volumes"
select="cv:NumberOfVolumes"/>
<property label="Volume"
select="cv:Volume"/>
<property label="Series Title"
select="cv:SeriesTitle"/>
<property label="Is Refereed"
select="cv:IsRefereed"/>
<property label="Description"
select="cv:Description"/>
</propertysheet>
</element>
<element match="cv:Books">
<title>Books</title>
<display-title>yes</display-title>
<type>cv:Books.Type</type>
<core-type>complexType</core-type>
<metadata>Collection</metadata>
<collection>
<record label="Book" select="cv:Book"/>
</collection>
</element>
<pattern match="Collection"/>
<pattern match="Record"/>
<pattern match="CategoryBinder"/>
<pattern match="Property" type="String"/>
...
</structure>
The structures so described can be thought of as an alternative schema, one that concentrates on the larger relationships between the pieces. Thus the <cv:Books> element gets described as a collection of <cv:Book> elements, while each <cv:Book> element in turn is made up of a set of properties, given in the associated order. The select attribute provides an XPath expression relative to the match attribute in the <element> description; in essence this is a match to the schema element. One advantage to this approach is that the properties can be rearranged, and the property select attributes can also be overridden to point to different elements defined by the corresponding XPath expressions.
Similarly, the generators also create default stubs for the various default metadata patterns. These pattern templates may be used to define CSS classes or establish other bindings (such as XBL bindings) in the initial generators, but more significantly, they also provide ways to change the default implementation.
Overriding MetaStructure
You can make a rather surprisingly robust application just with the default generated metastructure, though whether it will be pleasant to look at or even work with will be highly dependent upon the schema in question. It is more likely that you may want 85 percent of the functionality as is, but you may want to override the remaining 15 percent to handle special cases that are unique to this particular schema. This is the role of the overlays.
Whereas the base metastructure is automatically generated, the overlays are created by hand (though it's my intent to develop tools to generate the overlays through other user interfaces) and provide the means to shape the forms in a manner that better expresses the needs of the final application.
Each overlay document is similar to the best metastructure document in that it supports an <overlay> container element holding collections of <element> and <pattern> elements. In general, only those elements or patterns that are specifically being overridden need to be included.
<overlay id="cv-overlay-standard">
<element match="cv:Book">
<propertysheet>
<property label="Title" select="cv:TitleOfWork"/>
<property label="Publisher" select="cv:Publisher"/>
</propertysheet>
<label-style>color:blue;weight:bold;</label-style>
</element>
<pattern match="Record">
<box-style>border:inset 3px;</box-style>
</pattern>
</overlay>
In the overlay cv-overlay-standard, the first entry indicates that for the <cv:Book> element, the property sheet is replaced with a different one that has only two fields, while the label-style (the style of the label for the book control) is set to a bold blue. In the second entry, all elements that are of pattern Record are wrapped in a three-pixel border that surrounds both the label and the relevant control. Note that other properties on the element match, such as the title used for the label, remain the same as before; only those entries that are first-level children of the match element are overridden.
The processor that merges the overlay with the base metastructure looks in a system level file called conf.xml in order to determine which overlays to use, and in what order:
<conf>
<domain id="app" path="/db/app">
<topics>
<topic id="cv" namespace-prefix="cv"
namespace="http://www.metaphoricalweb.org/xmlns/2007/cv"
object-data="/db/app/cv/data"
object-template="/db/app/cv/templates/new.xml">
<overlay-set id="editor-en">
<overlay ref="cv-overlay-standard"/>
</overlay-set>
<overlay-set id="editor-fr">
<overlay ref="cv-overlay-standard"/>
<overlay ref="cv-overlay-fr"/>
</overlay-set>
</topic>
</topics>
</domain>
</conf>
The ROX processor can handle multiple accounts, so the domain specifies the account in question and gives pertinent information about namespaces, the location of critical resources and collections, and the like. In this particular case, the topic (cv) contains as children two overlay sets: cv-overlay-en and cv-overlay-fr for the English and French overlays of the editor respectively, and the control program which generates the overlays takes a parameter that specifies which overlay set will be applied to generate the output. In the French case, the ordering here is important; cv-overlay-standard is applied directly to the generated base metastructure first, then cv-overlay-fr is applied on the resulting metastructure. This final metastructure then defines the characteristics that will be used for the generation of the XForms.