Web-based XML Editing with W3C XML Schema and XSLT
April 30, 2003
W3C XML Schema (WXS) is an XML language for describing and constraining the content of XML documents. Using WXS to validate XML instance documents has become a common practice. Using a schema we can also go the other way around: create or edit a valid XML instance document using the information in the schema.
This article describes a technique in which an XML instance document can be edited through an automatically created form-based GUI, based on the schema of the instance document. The whole cycle of GUI creation (using XSLT), editing, and updating (using XUpdate) XML instances is presented here.
The following figure illustrates the general idea: an XML instance document that can be edited through a GUI, which is created from the corresponding schema.
|Figure 1. Desired system outline.|
Transforming Schemas Into GUIs
The first step, one might think, is the direct transformation of the schema through a processor (which can be an XSL transformation) to a GUI.
|Figure 2. Direction transformation of a schema into a form-based GUI|
The schema (labeled as XSD) is transformed through a processor into a GUI. The processor makes an input field for every (simple) element that it encounters in the XSD document. A possible approach for this step was introduced in Transforming XML Schemas in which the XSD could be transformed into a form-based GUI using XSLT.
In this article the whole concept is actually worked out for a web-based GUI, hence a servlet could be used to receive and process the input from the user. After the schema is processed the user can fill in the data into the input fields and the data is sent to the servlet. The servlet will then use this incoming data to make an XML document, which would be valid against the original schema.
The limitation of this approach is that it works only for the creation of a new XML instance document, as the processor can only transform the schema into a GUI. An existing XML instance cannot be edited, as the processor has no knowledge of transforming an XML instance document into a form-based GUI.
Editing an XML Instance Document
What we want is a processor which can take an existing XML instance document and create a form-based GUI so that we can edit the document. See the following figure.
|>Figure 3. Editing of an XML instance document.|
The concept shown in Figure 3 is as follows: instead of transforming the schema directly to a GUI, the processor will now make an XSLT stylesheet, which we call XSLGUI. This stylesheet knows exactly how to transform an XML instance document valid against our schema into a form-based GUI.
To give an example of how the concept works, imagine you have a schema document called Person.xsd in which you define what elements a person can have (e.g name, last_name, ...):
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="person"> <xsd:complexType> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="phone" type="xsd:string" minOccurs="1" maxOccurs="3"/> <xsd:element name="date_of_birth" type="xsd:date"/> <xsd:element name="course" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="course_name" type="xsd:string"/> <xsd:element name="start_date" type="xsd:date"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
Imagine that you also have created an instance document for an imaginary person called Marc (Marc.xml) using the Person.xsd:
<?xml version="1.0" encoding="UTF-8"?> <person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Person.xsd"> <name>Marc</name> <phone>0153816546</phone> <phone>0630458920</phone> <date_of_birth>1978-01-21</date_of_birth> <course> <course_name>TCP/IP</course_name> <start_date>2001-12-10</start_date> </course> <course> <course_name>Java Programming</course_name> <start_date>1997-08-01</start_date> </course> </person>
The cycle shown in Figure 3 will use the Person.xsd document to make an XSLT (XSLGUI) document, which is able to make a GUI based on the elements found in Marc.xml.
There are different approaches possible for the way XSLGUI can create a form-based GUI based on the instance document. The first approach would be using XForms, which is currently a W3C Candidate Recommendation. The XSLGUI should then produce the right XForms XML document based on the XML instance document (e.g Marc.xml). Using XForms, however, means that the browser should be XForms-enabled, and as XForms is not a recommendation yet, the commonly used browsers do not support it.
A second approach would be Apache Cocoon XMLForm. The main difference between Cocoon XMLForm and W3C XForms is that XMLForm can be used with any browser for any client device as it does not require that the clients understand the XForms markup (See XML Forms, Web Services and Apache Cocoon).
A possible third approach, presented in this article, is a combination of XPath, XUpdate, and W3C XML Schema validation. The reason we have chosen this approach is because it is not dependent on the browser (browsers do not support XForms yet) or on using Cocoon (if you choose XMLForms you have to use Cocoon).
For every (simple) element in Marc.xml (e.g. name, last_name, ...) the XSLGUI will make an input field. In a browser-based GUI the input fields have name and value attributes, and these two parameters are all we can send to our servlet. Therefore the XSLGUI sets the name of each form element that it makes for each element equal to the XPath position of that element in the XML document, in order to map the structure of the instance document. For instance the HTML input tag for the second phone number in our Marc.xml document will look like:
<input name="/person/phone" value="0630458920"/>
According to W3C's "Basic
HTML data types", the
name attribute of the
input tag must
begin with a letter and therefore "/person/phone" is not allowed to be used as
of the name attribute of the
input tag. We have tested this notation with a
servlet under Tomcat and it works. However it is possible to substitute the slashes
with some other permitted character, and then at the servlet side parse it back to
In order to produce this XPath we need our XSLGUI to keep track of the location
and the number of elements in our XML document. The following shows parts of our generated
XSLGUI. For all the non-complex elements a match like the one for "phone" is
produced. The path string which shows the position of the parent element in each match
be adjusted (if necessary) and passed on recursively. The number of occurrences of
element is also counted and used as the index in the XPath notation. For the
course, which is a
complexType element, no input field is
directly made but the path parameter is passed to its children with the
The following is a concise view of the XSLGUI document:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:strip-space elements="*"/> <xsl:template match="person"> <xsl:param name="root">/person</xsl:param> <html> <head> <title>person</title> </head> <body> <form name="xmsForm" action="xms.InputPage" method="post"> <xsl:apply-templates> <xsl:with-param name="path" select="$root"/> </xsl:apply-templates> <input type="submit" name="action" value="save"/> </form> </body> </html> </xsl:template> ... <xsl:template match="phone"> <xsl:param name="path"/> <xsl:variable name="index"> <xsl:number count="phone"/> </xsl:variable> <B>phone: </B> <!-- The output of the following will look like this: <input name="/person/phone" value="0630458920"/> --> <input> <xsl:attribute name="name"> <xsl:value-of select="concat($path,'/phone[', $index,']')"/> </xsl:attribute> <xsl:attribute name="value"> <xsl:value-of select="text()"/> </xsl:attribute> </input> </xsl:template> ... <xsl:template match="course"> <xsl:param name="path"/> <xsl:variable name="index"> <xsl:number count="course"/> </xsl:variable> <B>course </B> <xsl:apply-templates select="*"> <xsl:with-param name="path" select="concat($path,'/course[', $index,']')"/> </xsl:apply-templates> </xsl:template> ... </xsl:stylesheet>
As we can see, each created input field will have an XPath location as its "name",
represents exactly the position of that element in the XML instance document. Imagine
user changes the value of the second phone number from 0630458920 to 0150458920. When
user requests to save the changes, the servlet receives the input. It can now make
over all the input fields whose names are valid XPath notations and make an XUpdate document. For the second phone number,
the server receives a parameter with
The XUpdate document with the
update command would be:
<?xml version="1.0" encoding="UTF-8"?> <xu:modifications xmlns:xu="http://www.xmldb.org/xupdate"> <xu:update select="/person/phone"> 0150458920 </xu:update> </xu:modifications>
After the XUpdate document is created for all the inputs, it will be used on a copy of the original Marc.xml document to update it using JAXUP which defines an interface to update XML documents and provides an implementation of XML:DB Initiative's proposed XUpdate specification.
A validation on the copied version is carried out afterwards. If it is valid, it will be saved as the original document and otherwise the errors are returned to the user.
We have been talking about a processor which takes a WXS schema and makes the required transformation into "XSLGUI". The processor could be anything that is capable of creating the required output. For instance a combination of DOM and the Java language could be a processor. In our approach the processor is actually a combination of XSLT documents and transformers as can be seen in the following figure.
|Figure 5. XML Schema to XSLGUI processor.|
What we need is an XSLT stylesheet which takes our XSD and transforms it into the corresponding XSLGUI. We call this stylesheet "MetaXSLGUI".
The basic task of the MetaXSLGUI is as follows:
For every element make an
matchattribute equal to the name of the element.
If element is a complexType then add the
xsl:apply-templates select="*"function to the template with the appropriate parameters.
Add the right XSLT functions and elements to the
xsl:templatein step 1, so that the
xsl:templatecan produce the appropriate input elements when needed.
Here is sample code to give an idea of what a possible MetaXSLGUI would look like. W3C XML Schema has many features, and even though it is quite an effort to design a stylesheet that can handle every possible feature, theoretically it is not impossible to do so. It is only a matter of time before there is a stylesheet with such a capability. We hope this sample MetaXSLGUI can serve as a start in that direction.
This article introduced a new perspective on automatic form-based GUI generation based on XML Schema, using a single XSLT stylesheet, through which editing XML instance documents is possible. There are of course open issues, such as how to add new elements to an instance document and how to create an initial instance of the schema. These issues will be discussed in a forthcoming article