Subscribe to Dr. Macro's XML Rants

NOTE TO TOOL OWNERS: In this blog I will occasionally make statements about products that you will take exception to. My intent is to always be factual and accurate. If I have made a statement that you consider to be incorrect or innaccurate, please bring it to my attention and, once I have verified my error, I will post the appropriate correction.

And before you get too exercised, please read the post, date 9 Feb 2006, titled "All Tools Suck".

Wednesday, July 05, 2006

Reformulated CALS/OASIS Table Model: Mark I

OK, I think I've found a formulation for a table module that satisfies all my requirements. Thanks to my commentors for correcting my misunderstandings and pointing me in the right direction.

What I've done is provided two options for handling the "entry" element:

Option 1 retains the name "entry" and defines its content model as requiring an element of type "EntryContents". The entry contents element imposes no constraints (it's a generic container) and is abstract. Using schemas then define their own EntryContents-type element and put it in the entryContents substitution group. The "entry" element is defined as mixed so that the simple cases of entries containing just PCDATA work as they always have. But if you want to have subelements, you must wrap them. Because existing CALS/OASIS table processors will recognize the (local) name "entry" and don't care what the entry contains, it should just work (although your schema-specific styling within cells may need to account for the new wrapper element). This approach allows existing schema-unaware table processors to continue to work as they always have.

Option 2 defines a new type of entry "substitutableEntry" that is abstract and must be substituted in the using schema. This approach is closer to the intent of the original table model and its parameter entities but requires that general table processors be namespace and schema type aware. In this approach, you define your own element of type TableEntry, put it in the subtitutableEntry substitution group and then define whatever content constraints you want. This approach avoids an extra level of containment. While this approach nominally requires schema type awareness in fact a processor could just blindly assume that the direct children of "row" must be entries and process them without even checking their type names (because the table schema doesn't allow anything else inside "row" except "entry").

This approach could also be augmented by adding some sort of fixed "class=" attribute to each of the element types. This would still require schema-aware processing (to get the defaulted values) but not schema type awareness. I haven't done this because my processing use case wouldn't benefit from it.

Here is my reformulation of "entry"

<xs:element name="row">
<xs:complexType>
<xs:choice maxOccurs="unbounded" >
<xs:element ref="tbl:entry"/>
<xs:element ref="tbl:substitutableEntry"/>
</xs:choice>
<xs:attributeGroup ref="tbl:attlist-row"/>
</xs:complexType>
</xs:element>

<xs:complexType name="TableEntry">
<xs:attributeGroup ref="tbl:attlist-entry"/>
</xs:complexType>

<xs:element name="entry">
<xs:complexType mixed="true">
<xs:complexContent>
<xs:extension base="tbl:TableEntry">
<xs:sequence>
<xs:element ref="tbl:entryContentsContainer" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>

<xs:complexType name="GenericContainer"/>

<xs:element name="entryContentsContainer" abstract="true" type="tbl:GenericContainer">
</xs:element>

<xs:element name="substitutableEntry" type="tbl:TableEntry" abstract="true">
</xs:element>

This then allows either of these two approaches in the using schema:

<xs:element name="cell-contents" substitutionGroup="tbl:entryContentsContainer">
<xs:complexType>
<xs:complexContent>
<xs:extension base="tbl:GenericContainer">
<xs:group ref="btd:paracon" maxOccurs="unbounded" minOccurs="0"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>

<xs:element name="mytablecell" substitutionGroup="tbl:substitutableEntry">
<xs:complexType>
<xs:complexContent>
<xs:extension base="tbl:TableEntry">
<xs:group ref="btd:paracon" maxOccurs="unbounded"/>
<xs:attribute ref="tbl:specVersion"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>

If your table processor expects to see unqualified tag names in the document instance you can set the namespace on the tgroup start tag:

<btd:table>
<tgroup cols="5"
xmlns="http://www.example.com/namespaces/oasis/exchange-table-model">
<thead>
<row>
<entry>States</entry>
<entry>No. of eggs per capita</entry>
<entry>Percentage of farm wealth earned by poultry</entry>
<entry>No. of eggs per hen</entry>
<entry>Farm value of eggs per dozen </entry>
</row>
</thead>
...
</tgroup>
</btd:table>

Labels:

0 Comments:

Post a Comment

<< Home