This section explains introduces a configuration language based in XML. Traditionally different applications have stored their configuration settings in a variety of formats ranging from databases to text files, from the Windows registry to directory services like LDAP.
The most common configuration format employed by Unix applications is plain text files. The exact syntax employed inside the text file varies greatly from application to application: Samba uses a simple pair key/value Windows .INI format, Apache allows sections and nested subsections, Bind also structures information with sections delimited by curly braces, etc. There are advantages/disadvantages of having a text based configuration as opossed to a GUI, such as easy automation with scripts, remote administration, etc.
A XML based configuration language was designed with the following goals:
The XML configuration language is built on top of basic building blocks. These blocks represent parameters from a semantic point of view, for what they mean, not how they are represented. That is, if there is a directive "userName" that can accept the name of a person as its value, the directive is thought as being a directive of class string rather than thinking about the directive in terms of how would it be represented in a GUI (in an entry form). This decoupling between the meaning of the directive and the user interface representation is of great importance as it will become clear in the section about XML User Interface.
The current basic blocks are the following:
To understand the following sections, it is important that there are two components to consider:
A simple XML configuration file of a fictitious server could be:
<server> <name>Mike's server</name> <ipAddress>10.0.0.1</ipAddress> <port>80</port> </server>
But how it is possible to know, when a server tag is found, which elements are allowed inside, and which are the ranges of accepted values? We need a configuration directives metalanguage. The server directive could be described as follows:
<structure name="server" label="Server"> </syntax> <string name="name" label="Server Name"/> <string name="ipAddress" label="IP address"/> <number name="Port" label="Port"/> </syntax> </structure>
The syntax above will be explained in the following sections. It is important to note that although the XML standard has a similar mechanism for defining the structure of a document, called DTDs (Document Type Definitions) they are not suitable for this purpose. If only because DTDs define the structure of a document (which tag can appear where) but do not offer any information about the data hold by those elements. Other XML standards, like XML Schemas aim to solve this problem, but they were only early drafts at the time Comanche was written. As the standards mature a move to them will be considered.
A string element represents text values and has the following XML definition.
<string name="stringName" label="This briefly describes the directive"> <default>Some default value</default> </string>
This directive will be represented in the XML configuration file as:
<stringName>This is some value</stringName>
If the directive stringName does not appear in the configuration file, it will be assumed to have the value "Some default value".
The default value and tags are optional. A graphical representation could be the following:
A number elemenet represents numbers and has the following XML definition.
<number name="numberName" label="This briefly describes the directive"> <default>123456</default> </number>
This directive will be represented in the XML configuration file as:
<numberName>123456</numberName>
If the directive numberName does not appear in the configuration file, it will be assumed to have the value "123456".
The default value and tags are optional A graphical representation could be the following:
A boolean element can only hold two values, true or false.
<boolean name="booleanName" label="Boolean label"> <default>1</default> </boolean>
In the XML configuration, it will appear the following
<booleanName>1</booleanName>A graphical representation could be the following:
The values can be one of a collection of fixed ones
<choice name="choiceName" label="Choose a fruit"> <syntax> <option name="orange" value="Juicy orange" /> <option name="lemon" value="Acid lemon" /> </syntax> <default>orange</default> </choice>
This directive will be represented in the configuration file as:
<choiceName>lemon</choiceName>
If the directive choiceName does not appear in the configuration file, it will be assumed to have the value "orange".
The default value and tags are optional A graphical representation could be the following:
This element represents a fixed value. It will be used in other composite elements.
<label name="labelName" label="This is the value of the label" > </label>
The directive will be represented as:
<labelName>This is the value of the label</labelName>A graphical representation could be the following:
This is an element that is a composite of others. The directive is composed of other directives. The general XMl description of the directive is as follows:
<structure name="structureName" label="Description of the structure"> <syntax> (... Here comes the XMl description of the structure components ..) </syntax> </structure>
This is better explained through an example. Let's assume a directive "person", which is composed of three other directives: a name (string), a surname (string) and an age (number)
The description would be:
<structure name="person" label="Description of a person" > <syntax> <string name="name" label="Name" /> <string name="surname" label="Family name" /> <number name="age" label="Age"> <default>21</default> </number> </syntax> </structure>
A representation of an instance of this directive in the configuration file would be:
<person> <name>John</name> <surname>Smith</surname> <age>30</age> </person>
There is no default for the directive itself, but rather each one of the elements defines its own default.
A possible graphical representation:
A list is a collection of elements of the same type. The list element definition (the part inside the syntax tags) can be itself be described in terms of other basic building blocks.
<list name="listName" label="Comment about the list"> <syntax> (... XML description of the list elements ...) </syntax> <default> (... depends on the list element ...) </default> </list>
The following example illustrates the use of the list element:
<list name="userNames" label="Names of users"> <syntax> <string name="user" label="Name of the user" > <default>nobody</default> </string> </syntax> <default> <item>dani</item> <item></item> </default> </list>
An entry io the XML conf file that uses this list would be:
<userNames> <user>user1</user> <user>user2</user> </userNames>
A possible graphical representation:
When the user adds an element:
This element is similar to the structure element, but in this case instead of being a collection of elements, it is one (and only one) of the elements.
<alternate name="alternateName" label="some text describing the alternate" > <syntax> (... XML description of the possible elements ...) <syntax> <default> (... XML description of the element and value ...) </default> </alternate>As an example, the Apache bind directive is implementated as an alternate
<alternate name="bindAddress" label="Address to bind the server" > <syntax> <label name="allAddresses" label="All available addresses" /> <string name="specific" label="Specific address/domain-name" > </string> </syntax> <default><specific>127.0.0.1</specific></default> </alternate>
A possible graphical representation:
In the XML configuration file, a bindAddress directive would look like:
<bindAddress> <specific>10.0.0.1</specific> <bindAddress>
or if the web server is going to listen to all addresses available:
<bindAddress> <allAddresses/> </bindAddress>
These are the basic building blocks that, combined, can be used to create arbitrarily complex directives. Yet the rules are very simple.
These XML elements are manipulated in Tcl in a special way, that isolates the XML syntax details (that may change in the future) and allows similar elements to be accessed in a similar way (i.e reading a string or numeric value is done in a similar way)
The process is the following: a XML document containing the directives is parsed using a XML parser. This XML parser's callbacks are used to construct a Document Object Model representation of the XML document. A DOM representation of a XML document is a tree like structure of the document that can be accessed programtically. For example, the following XML document:
<server> <name>Daniel</name> <surname>Lopez</surname> </server>Its DOM representation would be:
server (element) | |---name (element) | | | \_ text node (value="Daniel") | |---surname (element) | \_text node (value="Lopez")
The DOM implementation allows navigation of the document. To get the value "Daniel" the steps are as follows:
That is, a xuiString encapsulates the functionality of a XML string element. This functionality can be accessed invoking different methods:
If the variable xuiStr contains the name of an object instance of a xuiString class it is possible to do the following in the Tcl programming language:
$xuiStr getValueThe previous Tcl code invokes the method getValue on the object referenced by the xuiStr variable. The result of the invocation will be the return of the value of the string. If the string was defined as:
<someString>Some value<</someString>And xuiStr contained a reference to an object that represents that someString XML code, getValue would return "Some value".
Similarly,
$xuiStr setValue "Another value"Will set the new value for the string. If the object is serialized back to XML, the result would be:
<someString>Another value</someString>
If the xuiObject is a xuiList, it has methods available to create, add, remove certain elements, etc.
If the xuiObject is a xuiList, it has methods available to create, add, remove certain elements, etc. Assuming $myList is a xuiList of strings defined by the following XML declaration:
<list name="myListName" label="Some comentary"> <syntax> <string name="someStringName" label="some label" /> </syntax> <default> <item>bla</item> </default> </list>
If $MyList has just been created it has a default content of one children with the value "bla", which XML representation would be:
<myListName> <item>bla</item> </myListName> set childList [$myList getChildren] # In Tcl, code in brackets [] is executed and the result is substituted. # The previous statement works as follows: # - Invokes the method getChildren on the $myList object # - Store the result on the childList variable # Now childList contains all the children of $myList, in this case only one, # a xuiString element with value "bla" puts [$childList getValue] # puts is the Tcl command for printing a value to the standard output # The code inside the brackets gets the value of the list element, in this # case it will print "bla" since we have a single element, which has that # value. set newChild [$myList newChild] # The newChild method invocation creates a new list element and the # reference is stored in the newChild variable $newChild setValue "foo" # This new child, which is of the type xuiString, is asigned the value "foo" $myList insertChild $newChild # Finally, the child is inserted at the end of the xuilist. # In summary: A new children has been created and inserted in the list. # If the object was serialized, the result would be the following: <myListName> <item>bla</item> <item>foo</item> </myListName>
This distinction between the XML representation of the object and the object itself is very important for a number of reasons: