Text only | Skip links
Skip links||IT Services, University of Oxford

1. Objectives

The aim of this exercise is to get you to understand a TEI ODD customization created by Roma, and create one from scratch using the newer features of ODD. You should be able to
  • add documentation to a TEI ODD customization
  • make modifications not possible in Roma
  • express modifications using pure ODD, rather than RELAX NG
  • create a new element

You should start by making a customization in Roma (make sure you include the transcr, textstructure and core modules), saving it, and loading the ODD file into oXygen. You'll find it useful to pretty-print this by pressing Meta-Shift-P (the Format and Indent button).

2. Adding documentation to a TEI ODD customization

You can add as much prose as you want before or after the <schemaSpec> element, to act as the documentation for your project.

Test this, by writing some useful prose (probably inside a <div>, and processing the file to get HTML documentation using oXygen or Roma.

Suppose in your prose section you want to discuss a particular group of elements? add this (or something similar) to your ODD:
<specList>
 <specDesc key="p"/>
 <specDesc key="patts="+"/>
 <specDesc key="patts="xml:id"/>
 <specDesc key="valList"/>
 <specDesc key="valListatts="type"/>
</specList>
make documentation and see the effect of each of these <specDesc> elements.

3. Modifications not possible in Roma

One of the things you cannot do in Roma is provide documentation for value lists.
  1. In your ODD file, change the place attribute of <add> to give it a closed <valList> containing just the values you want to support (eg just ‘above’ and <below>). Add <desc> elements to explain what each value means. The result should look a bit like this:
    <elementSpec mode="changeident="add">
     <attList>
      <attDef ident="placemode="change">
       <valList type="closedmode="replace">
        <valItem ident="above">
         <desc>above the current line</desc>
        </valItem>
        <valItem ident="below">
         <desc>below the current line</desc>
        </valItem>
       </valList>
      </attDef>
     </attList>
    </elementSpec>
    Look carefully here at the use of mode and make sure you understand why the <valList> is in ‘replace’ mode.
  2. Generate documentation and check you can see your changes.
  3. Generate a RELAX NG schema, and use it in oXygen to edit a file. Do you see the documentation values you specified when you go to add a place attribute on <add>?
  4. Repeat this exercise, providing a <valList> on another element. You will have to decide whether to use ‘replace’ or ‘add’ mode.

4. Expressing modifications using pure ODD

So far we have not needed to tinker much with content models. But now let us radically change the model of <div>. Edit your ODD file, and add a new stanza about <div>:

<elementSpec mode="changeident="div">
 <content>
  <alternate>
   <alternate maxOccurs="unboundedminOccurs="1">
    <classRef key="model.pLike"/>
    <classRef key="model.graphicLike"/>
   </alternate>
   <sequence maxOccurs="unboundedminOccurs="0">
    <classRef key="model.divLike"/>
   </sequence>
  </alternate>
 </content>
</elementSpec>

Do you understand what is happening here? Generate a schema, and create a document using it. What are you prompted for within a <div>?

Now you try. Alter <p> so that it only contains transcriptional elements (model.pPart.transcriptional), or lists (model.listLike) but not both. Look at the TEI Guidelines to check the model classes.

Make a schema and a document. How is it different from <p> in normal use? What is missing? Did model.listLike do what you expected?

5. Adding a constraint

It is perhaps surprising that our schema languages do not check pointers within a document (when we have, for example, a <ptr> with a target of #foo, we must have an xml:id with a value of foo somewhere in the current document). Let's use Schematron to check this.

Add a stanza in your ODD like this
<elementSpec mode="changeident="ptr">
 <constraintSpec ident="checkptrscheme="isoschematron">
  <constraint>
   <assert xmlns="http://purl.oclc.org/dsdl/schematron"
   
     test="//*[@xml:id=substring(current()/@target,2)]">
The pointer <value-of xmlns="http://purl.oclc.org/dsdl/schematron"
     select="@target"/>
has no corresponding ID</assert>
  </constraint>
 </constraintSpec>
</elementSpec>
This adds a brute force check that a target on <ptr> must have a corresponding ID. What are the two flaws with this rule? Can you see a way to improve it?

6. Creating a new element

Sometimes one just cannot resist thinking about adding a new element to the TEI. Your final task is to build one from scratch, using all the components of the ODD language.
  • It should be called <alien>
  • It should be allowed to appear in the same places as transcriptional elements
  • It should have a type attribute and a place attribute
  • It should be able to contain plain text, and the global elements like page and line breaks
  • It must not occur inside an <div> with a type of ‘verse’ (you'll need a constraint)
  • It needs an example and a description
(I leave it to you to work out what its semantics are)

Check this works in a schema and documentation. Test it against the file ex4-test.xml; don't forget to explain to oXygen that you are using Schematron rules in your schema, or you won't catch all the errors.

But that wasn't quite right - you are not supposed to add to the TEI. Change your element to be in the namespace http://www.dixit.eu/ns/ (add ns="http://www.dixit.eu/ns/" to the <elementSpec>). NOTE: you must add code like
<constraint>
 <ns xmlns="http://purl.oclc.org/dsdl/schematron"
  prefix="auri="http://www.dixit.eu/ns/"/>

</constraint>
declaring the namespace to Schematron and providing a prefix, inside your <constraintSpec>, or the schema generation will fail. See how it looks now in the schema.


Sebastian Rahtz. Date: October 2014
Copyright University of Oxford