Web-based XML Editing with W3C XML Schema and XSLT
by Ali Mesbah
|
Pages: 1, 2
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[2]" 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[2]" is not allowed to be used as
the value 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 the valid XPath notation.
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 will be adjusted (if necessary) and passed on
recursively. The number of occurrences of each 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 apply-template call.
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[2]" 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", which represents exactly the position of that element in the XML instance
document. Imagine the user changes the value of the second phone number from
0630458920 to 0150458920. When the user requests to save the changes, the servlet
receives the input. It can now make a loop 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 name="/person/phone[2]"
and value="0150458920"
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[2]">
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.
The Processor
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
xsl:templatewith thematchattribute 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 thexsl: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.
Conclusion
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
Resources
|

