by Eric van der Vlist is published by O'Reilly & Associates (ISBN: 0596004214)
It's good to design extensible schemas, but they make an impact only on developers who can extend our initial schema. A document valid per an extended flavor of our schema is likely to be invalid per our original schema.
By contrast, an open schema lets instances be extensible and allows the addition of content while still remaining valid against the original schema. Of course because the additions are unpredictable, the validation of their structure will be very lax, but extended documents will still be considered valid.
Designing and using open schemas is quite challenging because it gives more power to the XML user, and unexpected situations may result. The use of open schemas also conflicts with some best practices of schema usage: a totally open schema validates any well-formed XML document and is thus totally useless. On the other hand, closed schemas violate the fundamental principle of extensibility of XML, the extensible markup language.
There are several levels of openess from a totally closed schema in which nothing unexpected can happen, to the most extreme case, which allows any well-formed document. In RELAX NG, name classes (introduced in Chapter 10) are the basic blocks that will let you build the wildcards needed to open a schema We'll take a closer look at name classes before presenting the constructions most often used in open schemas.
Here I'll first recap the name classes seen in the previous chapter. You've seen how to use anyName to match any name from any namespace in the context of an element or an attribute:
<define name="anything"> <zeroOrMore> <choice> <element> <anyName/> <ref name="anything"/> </element> <attribute> <anyName/> </attribute> <text/> </choice> </zeroOrMore> </define> |
or:
anything = ( element * { anything } | attribute * { text } | text )* |
Then you saw how to remove specific namespaces from anyName using except and nsName:
<define name="foreign-elements"> <zeroOrMore> <element> <anyName> <except> <nsName ns=""/> <nsName ns="http://eric.van-der-vlist.com/ns/library"/> <nsName ns="http://eric.van-der-vlist.com/ns/person"/> </except> </anyName> <ref name="anything"/> </element> </zeroOrMore> </define> |
or:
default namespace lib = "http://eric.van-der-vlist.com/ns/library" namespace local = "" namespace hr = "http://eric.van-der-vlist.com/ns/person" .../... foreign-elements = element * - (local:* | lib:* | hr:*) { anything }* |
The two name class elements except and nsName shown in this example can be used independently. To define a name class for any name from the lib namespace, I can write:
<element> <nsName ns="http://eric.van-der-vlist.com/ns/library"/> <ref name="anything"/> </element> |
or:
element lib:* { anything } |
Elements and attributes have one and only one name. It's meaningless to associate them with several name classes, unless you do it using choice. The choice element provides a method of combining name classes. To define a name class for any name from the lib or hr namespaces, I can write:
<element> <choice> <nsName ns="http://eric.van-der-vlist.com/ns/library"/> <nsName ns="http://eric.van-der-vlist.com/ns/person"/> </choice> <ref name="anything"/> </element> |
or:
element lib:* | hr:* { anything } |
Finally, there is also a name class that operates on specific element or attribute names. To define a name class lib:name or hr:name, I can write:
<element> <choice> <name>libname</name> <name>hrname</name> </choice> <ref name="anything"/> </element> |
or:
element lib:name | hr:name { text } |
Note that the name name class expects a qualified name. These name classes can be combined pretty much as you like. You can also define a name class for any name from the hr namespace except the known elements:
<element> <nsName ns=ns="http://eric.van-der-vlist.com/ns/person"/> <except> <name>hr:author</name> <name>hr:name</name> <name>hr:born</name> <name>hr:dead</name> <except> </nsName> <ref name="anything"/> </element> |
or:
element hr:* - ( hr:author | hr:name | hr:born | hr:dead ) { anything } |
This definition allows for future extension of the hr namespace.
This text is released under the Free Software Foundation GFDL.