This Version: V 0.7 (3rd February 2003)
Latest Version: http://examplotron.org/
This namespace: http://examplotron.org/0/
Previous Version: V 0.6 (29 January 2003)
Examplotron 0.x is a proof of concept including this page, compile.xsl (a XSLT transformation that transforms examplotron documents into Relax NG schemas that validate "similar" documents) and a set of examples.
The description of the namespace version convention I intend to use for examplotron has been posted for discussion on xml-dev.
Note that this since release 0.5 Examplotron is no longer based on a XSLT validation with its own semantic but DSDL validation involving Relax NG and Schematron
Editor:
The purpose of examplotron is to use instance documents as a lightweight schema language-- eventually adding the information needed to guide a validator in the sample documents.
"Classical" XML validation languages such as DTDs, W3C XML Schema, Relax, Trex or Schematron rely on a modeling of either the structure (and eventually the datatypes) that a document must follow to be considered as valid or on the rules that needs to be checked.
This modeling relies on specific XML serialization syntaxes that need to be understood before one can validate a document and is very different from the instance documents and the creation of a new XML vocabulary involves both creating a new syntax and mastering a syntax for the schema.
Many tools (including popular XML editors) are able to generate various flavors of XML schemas from instance documents, but these schemas do not find enough information in the documents to be directly useable leaving the need for human tweaking and the need to fully understand the schema language.
Examplotron may then be used either as a validation language by itself, or to improve the generation of schemas expressed using other XML schema languages by providing more information to the schema translators.
Examplotron aims to be both very visual (John Cowan said that "its virtue is iconicity") and complete. Both aspects are contradictory and the principle of Examplotron is to follow the 80/20 rule and make no compromize for its iconicity for the 80% of the features which are most common and borrow the Relax NG elements in its own namespace to insure that it is complete.
The "iconic" 80% include:
This release in an intermediate release where most of the "iconic 80%" has been implemented and the "complemental 20%" left for a next release.
The obvious limitation of working with sample documents is that while this is very efficient to describe patterns that can be "shown" in a document, this cannot by itself be used to describe abstract "constructed" patterns.
To workaround this limitation, Examplotron relies on annotations, moving to an hybrid schema language involving both pure "schema by example" and modeling or rules construction.
Annotations through attributes are non intrusive and considered as part of the inconic 80% (the definition of mandatory attributes being the only exception which is done through an element).
Annotations through elements is done using elements imported from Relax NG and constitute the "complemental 20%". They include:
This first instance document (examplotron1.xml) is also a examplotron schema:
<?xml version="1.0" encoding="UTF-8"?> <foo> <bar>My first examplotron.</bar> <baz>Hello world!</baz> </foo>
This schema will validate all the documents without any namespace and the "same" structure, i.e. three element nodes (a document element of type "foo" with exactly two children elements "bar" and "baz") and no attributes.
The examplotron compiler (i.e. the compile.xsl XSLT sheet) transforms the examplotron schema into a Relax NG schema (examplotron1.rng) that can be applied to any document to check if it has the same structure.
The structure of examplotron1.rng (and therefore the transformation defined in compile.xsl) is very straightforward:
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='foo'> <element name='bar'> <text> <ega:example>My first examplotron.</ega:example> </text> </element> <element name='baz'> <text> <ega:example>Hello world!</ega:example> </text> </element> </element> </start> </grammar>
Don't let the declarations and annotations confuse you. We will see in the next sections the use of these declarations and the annotations (such as "<ega:example>Hello world!</ega:example>") are there to carry the samples from Examplotron to Relax NG and insure that the Relax NG schema could be converted back into Examplotron if needed.
Attributes are also supported as shown by examplotron2.xml:
<?xml version="1.0" encoding="UTF-8"?> <foo> <bar true="no longer">My first examplotron.</bar> <baz>Hello world</baz> </foo>
Which will include the definition of the "true" attribute as optional (examplotron2.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='foo'> <element name='bar'> <optional> <attribute name='true'> <ega:example true='no longer'/> </attribute> </optional> <text> <ega:example>My first examplotron.</ega:example> </text> </element> <element name='baz'> <text> <ega:example>Hello world</ega:example> </text> </element> </element> </start> </grammar>
Note that to declare mandatory attributes you would need to use the "complemental 20%".
What if we needed several elements "bar"? Just tell it (occurrences.eg):
<?xml version="1.0" encoding="UTF-8"?> <foo> <bar>My first examplotron.</bar> <bar>Hello world!</bar> </foo>
And this will give (occurrences.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns:ega="http://examplotron.org/annotations/" xmlns="http://relaxng.org/ns/structure/1.0" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="foo"> <oneOrMore> <element name="bar"> <text> <ega:example>My first examplotron.</ega:example> </text> </element> </oneOrMore> <ega:skipped> <bar xmlns="">Hello world!</bar> </ega:skipped> </element> </start> </grammar>
Examplotron has seen that several "bar" elements have been defined in sequence and interpreted this as a sign that one or more occurrences of "bar" were allowed. He has used the first instance of the "bar" element as a definition of its content and skipped the other instances.
Note that the two "bar" elements have to be defined in sequence to trigger this feature and that inserting an element between them (occurrences-non-seq.eg):
<?xml version="1.0" encoding="UTF-8"?> <foo> <bar>My first examplotron.</bar> <baz/> <bar>Hello world!</bar> </foo>
Would kill this magic (occurrences-non-seq.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="foo"> <element name="bar"> <text> <ega:example>My first examplotron.</ega:example> </text> </element> <element name="baz"> <empty/> </element> <element name="bar"> <text> <ega:example>Hello world!</ega:example> </text> </element> </element> </start> </grammar>
Issue: Should we remove this rule for interleave and mixed contents?
It is also possible to override the definition of the occurrences (examplotron3.xml):
<pre><?xml version="1.0" encoding="UTF-8"?> <foo xmlns:eg="http://examplotron.org/0/"> <bar eg:occurs="+">Hello world</bar> <!-- eg:occurs could also have been set to "*", "." or "?" --> </foo>
The value of the eg:occurs attributes can be "*" (0 or more), "+" (1 or more), "." (exactly one), "?" (0 or 1) or '-' (no occurrence) and defined the number of occurrences of the element (examplotron3.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='foo'> <!-- eg:occurs could also have been set to "*", "." or "?" --> <oneOrMore> <element name='bar'> <text> <ega:example>Hello world</ega:example> </text> </element> </oneOrMore> </element> </start> </grammar>
Note that using a "eg:occurs" attribute has the same effect on adjacent definitions of the same element than the insertion of an element with another name, (occurences-over.eg):
<?xml version="1.0" encoding="UTF-8"?> <foo xmlns:eg="http://examplotron.org/0/"> <bar>My first examplotron.</bar> <bar eg:occurs=".">This declaration "isolates" the previous one from the next one</bar> <bar>Hello world!</bar> <bar>This new declaration has the effect that the previous one will be considered as "oneOrMore".</bar> </foo>
Will give (occurences-over.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="foo"> <element name="bar"> <text> <ega:example>My first examplotron.</ega:example> </text> </element> <element name="bar"> <text> <ega:example>This declaration "isolates" the previous one from the next one</ega:example> </text> </element> <oneOrMore> <element name="bar"> <text> <ega:example>Hello world!</ega:example> </text> </element> </oneOrMore> <ega:skipped> <bar xmlns="" xmlns:eg="http://examplotron.org/0/"> This new declaration has the effect that the previous one will be considered as "oneOrMore". </bar> </ega:skipped> </element> </start> </grammar>
The "-" can be used to skip a definition which is then considered as an annotation. This is usefull especially to overide the effect of the previous rule when a "zeroOrMore" has been forced. For instance, to specify that we want "zeroOrMore" element "bar" while keeping two instances of them in the schema (occurences-ann.eg):
<?xml version="1.0" encoding="UTF-8"?> <foo xmlns:eg="http://examplotron.org/0/"> <bar eg:occurs="*">My first examplotron.</bar> <bar eg:occurs="-">Hello world!</bar> </foo>
Will give (occurences-ann.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="foo"> <zeroOrMore> <element name="bar"> <text> <ega:example>My first examplotron.</ega:example> </text> </element> </zeroOrMore> <ega:annotation> <bar xmlns="" xmlns:eg="http://examplotron.org/0/" eg:occurs="-">Hello world!</bar> </ega:annotation> </element> </start> </grammar>
This feature can also be used to add annotations as elements to a schema.
Examplotron does support namespaces without any known restriction using namespaces in the examplotron documents as in any instance document (examplotron4.xml):
<?xml version="1.0" encoding="UTF-8"?> <foo xmlns:eg="http://examplotron.org/0/" xmlns:bar="http://http://examplotron.org/otherns/"> <bar:bar eg:occurs="+">Hello world</bar:bar> </foo>
is straightforwardly translated into (examplotron4.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='foo'> <oneOrMore> <element ns='http://http://examplotron.org/otherns/' name='bar'> <text> <ega:example>Hello world</ega:example> </text> </element> </oneOrMore> </element> </start> </grammar>
When children elements and text nodes with non whitespace characters are found in an element, the content model is assumed to be mixed as defined by Relax NG (ie text nodes may appear everywhere between elements and the children elements may appear in any order). This schema (mixed.eg):
<?xml version="1.0" encoding="UTF-8"?> <p>This paragraph is <b>mixed content</b> as defined by <a href="http://relaxng.org">Relax NG</a></p>
Would be translated into:
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='p'> <mixed> <ega:example>This paragraph is </ega:example> <element name='b'> <text> <ega:example>mixed content</ega:example> </text> </element> <ega:example> as defined by </ega:example> <element name='a'> <optional> <attribute name='href'> <ega:example href='http://relaxng.org'/> </attribute> </optional> <text> <ega:example>Relax NG</ega:example> </text> </element> </mixed> </element> </start> </grammar>
Examplotron does its best to guess the simple types found in elements and attributes. The following W3C XML Schema datatypes are supported:
Note that Examplotron implementations do not check the values of the numeric fields of ISO 8601 date and time formats and will for instance interpret "9999-99-99+99:99" as a date. This feature is defined to facilitate the job of both schema authors and Examplotron validators: even though "9999-99-99+99:99" is not a valid date, it "looks" like a date and that should be enough for the iconic nature of Examplotron.
Most of the time, these inferences give a pretty accurate result and the following schema (iconic-types.eg):
<?xml version="1.0" encoding="UTF-8"?> <order no="1234" date="2003-02-01"> <quantity>1</quantity> <ref>AZERTY</ref> <item>Tee shirt</item> <price unit="USD">10.</price> </order>
gives (iconic-types.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='order'> <optional> <attribute name='no'> <data type='integer'> <ega:example no='1234'/> </data> </attribute> </optional> <optional> <attribute name='date'> <data type='date'> <ega:example date='2003-02-01'/> </data> </attribute> </optional> <element name='quantity'> <data type='integer'> <ega:example>1</ega:example> </data> </element> <element name='ref'> <text> <ega:example>AZERTY</ega:example> </text> </element> <element name='item'> <text> <ega:example>Tee shirt</ega:example> </text> </element> <element name='price'> <optional> <attribute name='unit'> <ega:example unit='USD'/> </attribute> </optional> <data type='decimal'> <ega:example>10.</ega:example> </data> </element> </element> </start> </grammar>
Text nodes which do not obviously belong to one of the supported datatypes are translated as "text" patterns and this is also the case for any text pattern (whatever guesses could be made) appearing in an interleave (or mixed) content model (the latest is necessary to match a restriction of Relax NG).
We have seen how to specify text only, unordered elements only and mixed content models through the "iconic" features of Examplotron. The "eg:content" attribute gives full control over the content model and overides the guesses done by Examplotron from the content model of the schema. This attribute can take the values:
For instance, to request that the schema above does not enforce the relative order of the children elements of the "order" element, "eg:content" should be set to "eg:interleave", such as (interleave.eg):
<?xml version="1.0" encoding="UTF-8"?> <order no="1234" date="2003-02-01" eg:content="eg:interleave" xmlns:eg="http://examplotron.org/0/"> <quantity>1</quantity> <ref>AZERTY</ref> <item>Tee shirt</item> <price unit="USD">10.</price> </order>
gives (interleave.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='order'> <interleave> <optional> <attribute name='no'> <data type='integer'> <ega:example no='1234'/> </data> </attribute> </optional> <optional> <attribute name='date'> <data type='date'> <ega:example date='2003-02-01'/> </data> </attribute> </optional> <element name='quantity'> <data type='integer'> <ega:example>1</ega:example> </data> </element> <element name='ref'> <text> <ega:example>AZERTY</ega:example> </text> </element> <element name='item'> <text> <ega:example>Tee shirt</ega:example> </text> </element> <element name='price'> <optional> <attribute name='unit'> <ega:example unit='USD'/> </attribute> </optional> <data type='decimal'> <ega:example>10.</ega:example> </data> </element> </interleave> </element> </start> </grammar>
"eg:mixed" can be used to force a content model to be mixed even if it doesn't contain any text node in its schema, for instance (mixed-forced.eg):
<?xml version="1.0" encoding="UTF-8"?> <p eg:content="eg:mixed" xmlns:eg="http://examplotron.org/0/"> <b eg:occurs="*">Bold text</b> <a href="uri" eg:occurs="*">Hypertext link</a> </p>
gives (mixed-forced.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='p'> <mixed> <zeroOrMore> <element name='b'> <text> <ega:example>Bold text</ega:example> </text> </element> </zeroOrMore> <zeroOrMore> <element name='a'> <optional> <attribute name='href'> <ega:example href='uri'/> </attribute> </optional> <text> <ega:example>Hypertext link</ega:example> </text> </element> </zeroOrMore> </mixed> </element> </start> </grammar>
"eg:group" may be used to force a mixed content to be ordered. For instance, even if it is often considered to be a bad practice, one might want to define (group.eg):
<?xml version="1.0" encoding="UTF-8"?> <price eg:content="eg:group" xmlns:eg="http://examplotron.org/0/"> <currency>Euro</currency>25 </price>
and impose that the "currency" element precedes the text node. This would give (group.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='price'> <element name='currency'> <text> <ega:example>Euro</ega:example> </text> </element> <text> <ega:example>25 </ega:example> </text> </element> </start> </grammar>
Note that in this case, the text node cannot be defined as a "data" and its datatype cannot be enforced (this is a restriction of Relax NG).
The last Relax NG compositors (choice) has not been implemented since it doesn't seem very useful as a compositor for the whole content of an element.
Note that the prefix "eg" is reserved for this usage and should be used even if the namespace for Examplotron had been assigned to another prefix. The previous schema is thus strictly equivalent to the following one (mixed-forced-ns.eg):
<?xml version="1.0" encoding="UTF-8"?> <p foo:content="eg:mixed" xmlns:foo="http://examplotron.org/0/"> <b>bold</b> <a href="uri">link</a> </p>
As for content models, the assumption done by Examplotron for simple types may be overidden. For elements, simple types may be specified using the eg:content attribute. There is no risk of confusion since the usage of eg:content to specify a compositor implies that the element has children elements while the usage to define a simple type implies that the element is text only. Furthermore, the semantic of defining a specificity of the content is the same for both usages and using two different attributes would have created a risk of incoherencies between their usages.
The datatype is defined using a prefixed name and in addition to "eg", a new prefixes is reserved and may be used without namespace declarations: "xsd" identifies the W3C XML Schema datatypes.
When a datatype is specified for an element, the content of the element is skipped.
This feature can be used to give more restictive type declarations (for instance xs:byte instead of integer) and also for schemas in which documentation is placed in the elements. For instance (forced-types.eg):
<?xml version="1.0" encoding="UTF-8"?> <order no="1234" date="2003-02-01" eg:content="eg:group" xmlns:eg="http://examplotron.org/0/"> <quantity eg:content="xsd:nonNegativeInteger"> Number of ordered items </quantity> <ref eg:content="xsd:token"> Item's reference (see the <a href="ref-list.html">reference list</a>). </ref> <item eg:content="xsd:token"> Description of the item </item> <price unit="USD" eg:content="xsd:decimal"> Unit price of the item </price> </order>
Which would give (forced-types.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='order'> <optional> <attribute name='no'> <data type='integer'> <ega:example no='1234'/> </data> </attribute> </optional> <optional> <attribute name='date'> <data type='date'> <ega:example date='2003-02-01'/> </data> </attribute> </optional> <element name='quantity'> <ega:skipped> Number of ordered items </ega:skipped> <data type='nonNegativeInteger'/> </element> <element name='ref'> <ega:skipped> Item's reference (see the <a xmlns='' xmlns:eg='http://examplotron.org/0/' href='ref-list.html'>reference list</a>). </ega:skipped> <data type='token'/> </element> <element name='item'> <ega:skipped> Description of the item </ega:skipped> <data type='token'/> </element> <element name='price'> <optional> <attribute name='unit'> <ega:example unit='USD'/> </attribute> </optional> <ega:skipped> Unit price of the item </ega:skipped> <data type='decimal'/> </element> </element> </start> </grammar>
Note that the content which is skipped is now embedded in a "ega:skipped" annotation instead of a "ega:example" which is reserved for content having be used for inferencing a model.
To force a type for an attribute, we need to use a specific syntax since attributes can't hold "eg:content" attributes... The trick here is to include the datatype in curly braces ({}). For instance (forced-types-att.eg):
<?xml version="1.0" encoding="UTF-8"?> <order no="{xsd:unsignedInt}" date="2003-02-01"> <quantity>1</quantity> <ref>AZERTY</ref> <item>Tee shirt</item> <price unit="{xsd:NMTOKEN}">10.</price> </order>
Which would give (forced-types-att.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='order'> <optional> <attribute name='no'> <data type='unsignedInt'/> </attribute> </optional> <optional> <attribute name='date'> <data type='date'> <ega:example date='2003-02-01'/> </data> </attribute> </optional> <element name='quantity'> <data type='integer'> <ega:example>1</ega:example> </data> </element> <element name='ref'> <text> <ega:example>AZERTY</ega:example> </text> </element> <element name='item'> <text> <ega:example>Tee shirt</ega:example> </text> </element> <element name='price'> <optional> <attribute name='unit'> <data type='NMTOKEN'/> </attribute> </optional> <data type='decimal'> <ega:example>10.</ega:example> </data> </element> </element> </start> </grammar>
Datatypes from the Relax NG DTD compatibility library (ie ID, IDREF and IDREFS) can also be used using a third "magic prefix", "dtd". . For instance (forced-types-att-dtd.eg):
<?xml version="1.0" encoding="UTF-8"?> <library> <book id="{dtd:ID}"> <title>Being a Dog Is a Full-Time Job</title> <author-refs idref="{dtd:IDREFS}"/> </book> <author id="{dtd:ID}"> <name>Charles M Schulz</name> </author> </library>
Which would give (forced-types-att-dtd.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='library'> <element name='book'> <optional> <attribute name='id'> <data type='ID' datatypeLibrary='http://relaxng.org/ns/compatibility/datatypes/1.0'/> </attribute> </optional> <element name='title'> <text> <ega:example>Being a Dog Is a Full-Time Job</ega:example> </text> </element> <element name='author-refs'> <optional> <attribute name='idref'> <data type='IDREFS' datatypeLibrary='http://relaxng.org/ns/compatibility/datatypes/1.0'/> </attribute> </optional> </element> </element> <element name='author'> <optional> <attribute name='id'> <data type='ID' datatypeLibrary='http://relaxng.org/ns/compatibility/datatypes/1.0'/> </attribute> </optional> <element name='name'> <text> <ega:example>Charles M Schulz</ega:example> </text> </element> </element> </element> </start> </grammar>
Other libraries may be used as well but a prefix need to be declared for them (forced-types-other.eg):
<?xml version="1.0" encoding="UTF-8"?> <order no="{py:int}" date="2003-02-01" xmlns:py="http://namespaces.xmlschemata.org/xvif/python-types" xmlns:eg="http://examplotron.org/0/"> <quantity eg:content="py:int">1</quantity> <ref>AZERTY</ref> <item>Tee shirt</item> <price unit="{py:float}">10.</price> </order>
Which would give (forced-types-other.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="order"> <optional> <attribute name="no"> <data xmlns:py="http://namespaces.xmlschemata.org/xvif/python-types" type="py:int"/> </attribute> </optional> <optional> <attribute name="date"> <data type="date"> <ega:example date="2003-02-01"/> </data> </attribute> </optional> <element name="quantity"> <ega:skipped>1</ega:skipped> <data xmlns:py="http://namespaces.xmlschemata.org/xvif/python-types" type="py:int"/> </element> <element name="ref"> <text> <ega:example>AZERTY</ega:example> </text> </element> <element name="item"> <text> <ega:example>Tee shirt</ega:example> </text> </element> <element name="price"> <optional> <attribute name="unit"> <data xmlns:py="http://namespaces.xmlschemata.org/xvif/python-types" type="py:float"/> </attribute> </optional> <data type="decimal"> <ega:example>10.</ega:example> </data> </element> </element> </start> </grammar>
Up to now, we've seen less control over attributes and this primarly due to the fact that XML attributes can't have a structure which would embed all the annotations we need to control them in a schema. To solve this, Examplotron uses the usual workaround that changes attrinbutes int elements and attributes can also be defined using a "eg:attribute" element (att-occurs.eg):
<?xml version="1.0" encoding="UTF-8"?> <foo xmlns:eg="http://examplotron.org/0/"> <eg:attribute name="bar">1</eg:attribute> </foo>
Which is translated into (att-occurs.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="foo"> <attribute name="bar"> <data type="integer"> <ega:example>1</ega:example> </data> </attribute> </element> </start> </grammar>
Note that by default, attributes defined using "eg:attribute" are mandatory. This is because one of the main reasons for defining attributes using "eg:attribute" is to define mandatory attributes. The number of occurrences and datatype could be overriden using "eg:occurs" and "eg:content" like it is the case for elements.
Let's take an example from W3C XML Schema part 0 to illustrate this point (po.eg):
<?xml version="1.0"?> <purchaseOrder orderDate="1999-10-20"> <shipTo country="US"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </shipTo> <billTo country="US"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <comment>Hurry, my lawn is going wild!</comment> <items> <item partNum="872-AA"> <productName>Lawnmower</productName> <quantity>1</quantity> <USPrice>148.95</USPrice> <comment>Confirm this is electric</comment> </item> <item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </items> </purchaseOrder>
This schema can be used straight away and gives (po.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="purchaseOrder"> <optional> <attribute name="orderDate"> <data type="date"> <ega:example orderDate="1999-10-20"/> </data> </attribute> </optional> <element name="shipTo"> <optional> <attribute name="country"> <ega:example country="US"/> </attribute> </optional> <element name="name"> <text> <ega:example>Alice Smith</ega:example> </text> </element> <element name="street"> <text> <ega:example>123 Maple Street</ega:example> </text> </element> <element name="city"> <text> <ega:example>Mill Valley</ega:example> </text> </element> <element name="state"> <text> <ega:example>CA</ega:example> </text> </element> <element name="zip"> <data type="integer"> <ega:example>90952</ega:example> </data> </element> </element> <element name="billTo"> <optional> <attribute name="country"> <ega:example country="US"/> </attribute> </optional> <element name="name"> <text> <ega:example>Robert Smith</ega:example> </text> </element> <element name="street"> <text> <ega:example>8 Oak Avenue</ega:example> </text> </element> <element name="city"> <text> <ega:example>Old Town</ega:example> </text> </element> <element name="state"> <text> <ega:example>PA</ega:example> </text> </element> <element name="zip"> <data type="integer"> <ega:example>95819</ega:example> </data> </element> </element> <element name="comment"> <text> <ega:example>Hurry, my lawn is going wild!</ega:example> </text> </element> <element name="items"> <oneOrMore> <element name="item"> <optional> <attribute name="partNum"> <ega:example partNum="872-AA"/> </attribute> </optional> <element name="productName"> <text> <ega:example>Lawnmower</ega:example> </text> </element> <element name="quantity"> <data type="integer"> <ega:example>1</ega:example> </data> </element> <element name="USPrice"> <data type="decimal"> <ega:example>148.95</ega:example> </data> </element> <element name="comment"> <text> <ega:example>Confirm this is electric</ega:example> </text> </element> </element> </oneOrMore> <ega:skipped> <item xmlns="" partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </ega:skipped> </element> </element> </start> </grammar>
However, this doesn't show the similarity between "billTo" and "shipTo" which have the same structure. To do so, we can use a new attribute "eg:define" in one of the instances of this structure and use "eg:content" to reference this definition in the other instances (po-id.eg):
<?xml version="1.0"?> <purchaseOrder orderDate="1999-10-20" xmlns:eg="http://examplotron.org/0/"> <shipTo country="US" eg:define="address"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </shipTo> <billTo country="US" eg:content="address"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <comment>Hurry, my lawn is going wild!</comment> <items> <item partNum="872-AA"> <productName>Lawnmower</productName> <quantity>1</quantity> <USPrice>148.95</USPrice> <comment>Confirm this is electric</comment> </item> <item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </items> </purchaseOrder>
This will generate a named pattern with the definition and references where needed (po-id.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="purchaseOrder"> <optional> <attribute name="orderDate"> <data type="date"> <ega:example orderDate="1999-10-20"/> </data> </attribute> </optional> <element name="shipTo"> <ref name="address" ega:def="true"/> </element> <element name="billTo"> <ref name="address"> <ega:skipped> <billTo xmlns="" xmlns:eg="http://examplotron.org/0/" country="US" eg:content="address"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> </ega:skipped> </ref> </element> <element name="comment"> <text> <ega:example>Hurry, my lawn is going wild!</ega:example> </text> </element> <element name="items"> <oneOrMore> <element name="item"> <optional> <attribute name="partNum"> <ega:example partNum="872-AA"/> </attribute> </optional> <element name="productName"> <text> <ega:example>Lawnmower</ega:example> </text> </element> <element name="quantity"> <data type="integer"> <ega:example>1</ega:example> </data> </element> <element name="USPrice"> <data type="decimal"> <ega:example>148.95</ega:example> </data> </element> <element name="comment"> <text> <ega:example>Confirm this is electric</ega:example> </text> </element> </element> </oneOrMore> <ega:skipped> <item xmlns="" xmlns:eg="http://examplotron.org/0/" partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </ega:skipped> </element> </element> </start> <define name="address"> <optional> <attribute name="country"> <ega:example country="US"/> </attribute> </optional> <element name="name"> <text> <ega:example>Alice Smith</ega:example> </text> </element> <element name="street"> <text> <ega:example>123 Maple Street</ega:example> </text> </element> <element name="city"> <text> <ega:example>Mill Valley</ega:example> </text> </element> <element name="state"> <text> <ega:example>CA</ega:example> </text> </element> <element name="zip"> <data type="integer"> <ega:example>90952</ega:example> </data> </element> </define> </grammar>
This mechanism can be used without reference to force the definition of a named pattern for the content of an element or attribute and we could ask that the "item" and "purchaseOrder" elements are described as named patterns (po-ct.eg):
<?xml version="1.0"?> <purchaseOrder orderDate="1999-10-20" xmlns:eg="http://examplotron.org/0/" eg:define="po"> <shipTo country="US" eg:define="address"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </shipTo> <billTo country="US" eg:content="address"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <comment>Hurry, my lawn is going wild!</comment> <items> <item partNum="872-AA" eg:define="item"> <productName>Lawnmower</productName> <quantity>1</quantity> <USPrice>148.95</USPrice> <comment>Confirm this is electric</comment> </item> <item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </items> </purchaseOrder>
Which will give (po-ct.eg):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="purchaseOrder"> <ref name="po" ega:def="true"/> </element> </start> <define name="po"> <optional> <attribute name="orderDate"> <data type="date"> <ega:example orderDate="1999-10-20"/> </data> </attribute> </optional> <element name="shipTo"> <ref name="address" ega:def="true"/> </element> <element name="billTo"> <ref name="address"> <ega:skipped> <billTo xmlns="" xmlns:eg="http://examplotron.org/0/" country="US" eg:content="address"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> </ega:skipped> </ref> </element> <element name="comment"> <text> <ega:example>Hurry, my lawn is going wild!</ega:example> </text> </element> <element name="items"> <oneOrMore> <element name="item"> <ref name="item" ega:def="true"/> </element> </oneOrMore> <ega:skipped> <item xmlns="" xmlns:eg="http://examplotron.org/0/" partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </ega:skipped> </element> </define> <define name="address"> <optional> <attribute name="country"> <ega:example country="US"/> </attribute> </optional> <element name="name"> <text> <ega:example>Alice Smith</ega:example> </text> </element> <element name="street"> <text> <ega:example>123 Maple Street</ega:example> </text> </element> <element name="city"> <text> <ega:example>Mill Valley</ega:example> </text> </element> <element name="state"> <text> <ega:example>CA</ega:example> </text> </element> <element name="zip"> <data type="integer"> <ega:example>90952</ega:example> </data> </element> </define> <define name="item"> <optional> <attribute name="partNum"> <ega:example partNum="872-AA"/> </attribute> </optional> <element name="productName"> <text> <ega:example>Lawnmower</ega:example> </text> </element> <element name="quantity"> <data type="integer"> <ega:example>1</ega:example> </data> </element> <element name="USPrice"> <data type="decimal"> <ega:example>148.95</ega:example> </data> </element> <element name="comment"> <text> <ega:example>Confirm this is electric</ega:example> </text> </element> </define> </grammar>
In order to describe more complex rules, it is possible to define assertions (i.e. statements that need to be met) as XPath expressions using "eg:assert" attributes (examplotron5.xml):
<?xml version="1.0" encoding="UTF-8"?> <foo xmlns:eg="http://examplotron.org/0/" eg:assert="sum(percent)=100"> <!-- The sum of the values of the "percent" element needs to be equal to 100 --> <percent eg:occurs="+">100</percent> </foo>
The implementation of this feature is optional and may may vary depending on the architecture of the implementation. One of the possibilities is to generate Schematron embedded assertions as supported by Sun's MSV (examplotron5.rng):
<?xml version='1.0' encoding='UTF-8'?> <grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:ega='http://examplotron.org/annotations/' xmlns:sch='http://www.ascc.net/xml/schematron' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> <start> <element name='foo'> <!-- The sum of the values of the "percent" element needs to be equal to 100 --> <sch:assert test='sum(percent)=100'/> <oneOrMore> <element name='percent'> <data type='integer'> <ega:example>100</ega:example> </data> </element> </oneOrMore> </element> </start> </grammar>
Assertions can be used without restriction on document using namespaces, but please remember that XPath expressions do not support default namespaces (examplotron6.xml):
<?xml version="1.0" encoding="UTF-8"?> <foo:foo xmlns:eg="http://examplotron.org/0/" eg:assert="sum(bar:percent)=100" xmlns:foo="http://examplotron/otherns/foo" xmlns:bar="http://examplotron/otherns/bar"> <bar:percent eg:occurs="+">100</bar:percent> </foo:foo>
To deal with possible redefinitions of namespace prefixes, the compiler copies all the namespaces nodes found in the element where the assertion is found in the template (examplotron6.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:ega="http://examplotron.org/annotations/" xmlns:sch="http://www.ascc.net/xml/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="foo" ns="http://examplotron/otherns/foo"> <sch:assert xmlns:eg="http://examplotron.org/0/" xmlns:foo="http://examplotron/otherns/foo" xmlns:bar="http://examplotron/otherns/bar" test="sum(bar:percent)=100"/> <oneOrMore> <element name="percent" ns="http://examplotron/otherns/bar"> <data type="integer"> <ega:example>100</ega:example> </data> </element> </oneOrMore> </element> </start> </grammar>
Many thanks to David Carlisle for this tip.
This mailing list is for discussing issues, bugs, questions and future development of Examplotron.
To subscribe, send a mail to [email protected] with "subscribe" in the subject or body.
This CVS repository gives you access on the detailed history of the documents composing the Examplotron distribution.
This database gives you access to bug and feature requests reports posted for Examplotron. Feel free to use it to post your own reports.
This documentation has been written as a RDDL document and this section will be developed to include more resources related to examplotron.
This compiler is a XSLT transformation that compiles an examplotron schema into a XSLT transformation that can be used to validate documents that are conform to this schema.
The compilation is known to suceed with Saxon. It should be able to run the compiler using any XSLT processor, however this transformation happens to be quite challenging for the XSLT processor and problems are known with XT (transformation aborted for lack of support of the namespace axis), libxslt (bug 105116) and 4xslt (bugs 679360 and 679374). The resulting schema must use a Relax NG processor (with support for embedded Schematron rules to support eg:assert).
This W3C XML Schema (Proposed Recommendation, 16 March 2001) schema describes the examplotron vocabulary and can be imported in W3C XML Schema to validate examplotron schemas.
A CSS stylesheet borrowed from RDDL used to provide the "look-and-feel" of this document, suitable in general for RDDL documents.
Original version of the previous CSS stylesheet on rddl.org.
The chapter 7. of the XYZFind Server User's Guide described a schema language used by XYZFind Server that is very similar to examplotron (no longer available online).
This early proposal for XSL proposed a syntax similar to the one used by examplotron for expressing patterns.
Home page of the Relax NG Oasis TC.
I have been pleasantly surprised after a couple of hours working on examplotron that this simple tool was beginning to be useful while still very simple (or simplistic).
The current version is already a powerful tool that can be used to validate documents.
It can be used as a main validation tool, or as a complement of a more classical validation tool, for instance, to add additional requirements and constraints to existing vocabularies when an application is using a subset of a vocabulary.
This being said, the simplicity of the tools is leaving room for many applications and extensions on which your feedback is welcome:
Many thanks to the many people that have given me hints, ideas or encouragements or even let me think that examplotron could be the best invention since the French baguette.
Note: the French baguette is another very simple invention made only of flour, salt, yeast and water (exactly like examplotron that is made out of XML 1.0, Namespaces in XML 1.0, XPath 1.0 and XSLT 1.0). The Englo-American sliced bread (often used in this context), involving more ingredients and postprocessing is far more complex and does obviously not belong to the same category than examplotron.
Non normative list (by chronological order): Simon St.Laurent, Edd Dumbill, John Cowan, Len Bullard, Rick Jelliffe, Evan Lenz, Dan Brickley, Jonathan Borden, David Mundie, David Carlisle, Murata Makoto, Cyril Jandia, Amelia A. Lewis, Gavin Thomas Nicol, Tim Mueller-Seydlitz, Michael Champion, Wendell Piez...
Major architectural change with constant set of features.
Bug fixes
Major release
Copyright (c) 2001-2003 Eric van der Vlist
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ERIC VAN DER VLIST BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.