tdom::schema -
Create a schema validation command
package require tdom tdom::schema cmdName
This command creates validation commands with a simple API. The validation commands have methods to define a grammer and are able to validate XML or DOM trees (and to some degree other kind of hierarchical data) against this grammer.
Additionally, a validation command may be used as argument to the -validateCmd option of the dom parse and the expat commands to enable validation additional to what they otherwise do.
The valid methods of the created commands are:
Schema definition scripts are ordinary Tcl scripts that are evaluatend in the namespace tdom::schema. Several schema definition commands in this tcl namespace allow to define a wide variety of document structures. Every schema definition command establish a validation constrain on the content which all has to match, leaving no unmatched content to render the content as valid.
The schema definition commands are:
Serveral schema definition commands expects a quantifier as one of their arguments, which specifies how often the content particle specified by the command is expected. The valid values for a quant argument are:
If an optional quantifier is missing then it defaults to ! - the content particle must occur exactly once in valid documents.
The XML Schema Part 0: Primer Second Edition (https://www.w3.org/TR/xmlschema-0/) starts with this example schema:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:annotation> <xsd:documentation xml:lang="en"> Purchase order schema for Example.com. Copyright 2000 Example.com. All rights reserved. </xsd:documentation> </xsd:annotation> <xsd:element name="purchaseOrder" type="PurchaseOrderType"/> <xsd:element name="comment" type="xsd:string"/> <xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType> <xsd:complexType name="USAddress"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="street" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="state" type="xsd:string"/> <xsd:element name="zip" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/> </xsd:complexType> <xsd:complexType name="Items"> <xsd:sequence> <xsd:element name="item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="quantity"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="USPrice" type="xsd:decimal"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="partNum" type="SKU" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <!-- Stock Keeping Unit, a code for identifying products --> <xsd:simpleType name="SKU"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}-[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>
A somewhat one-to-one translation of that into a tDOM schema defintion script would be:
tdom::schema grammar grammar define { # Purchase order schema for Example.com. # Copyright 2000 Example.com. All rights reserved. element purchaseOrder {ref PurchaseOrderType} element comment {text} defpattern PurchaseOrderType { element shipTo {ref USAddress} element billTo {ref USAddress} element comment ? element items attribute orderDate } defpattern USAddress { element name ! {text} element street ! {text} element city ! {text} element state ! {text} element zip ! {text isNumber} attribute country ! {text {fixed "US"}} } defelement items { element item * { element product ! {text} element quntity ! {text {maxExcluse 100}} element USPrice ! {text isNumber} element comment element shipDate ? {text isDate} attribute partNum ! {text {pattern "\d{3}-[A-Z]{2}"}} } } }
The RELAX NG Tutorial (http://relaxng.org/tutorial-20011203.html) starts with this example:
Consider a simple XML representation of an email address book: <addressBook> <card> <name>John Smith</name> <email>js@example.com</email> </card> <card> <name>Fred Bloggs</name> <email>fb@example.net</email> </card> </addressBook> The DTD would be as follows: <!DOCTYPE addressBook [ <!ELEMENT addressBook (card*)> <!ELEMENT card (name, email)> <!ELEMENT name (#PCDATA)> <!ELEMENT email (#PCDATA)> ]> A RELAX NG pattern for this could be written as follows: <element name="addressBook" xmlns="http://relaxng.org/ns/structure/1.0"> <zeroOrMore> <element name="card"> <element name="name"> <text/> </element> <element name="email"> <text/> </element> </element> </zeroOrMore> </element>
This schema definition script will do the same:
tdom::schema grammar grammar define { defelement addressBook { element card * } defelement card { element name element email } foreach e {name email} { defelement $e {text} } }