The Xopus Wysiwyg XML Editor allows to edit the content of XML files transparently within the Web browser, without confronting the user with xml/xsl tags. It is currently tested to work with IE 5.5 and IE 6.0.
Xopus communicates with the http server through a series of requests, and expects the server to return appropriate responses. The structure and content of these requests and responses is defined and explained below. To integrate Xopus into the Cocoon environment, we need to implement an interface to handle those requests.
The requests Xopus sends to the server and the responses it expects are valid xml streams according to the definitions below.
Xopus uses 3 requests to get the contents of the corresponding xml, xsl and xsd files for the content to be edited. This file trio follows the well-known MVC (Model-View-Controller) pattern:
File Type | Extension | Function |
---|---|---|
XML File | .xml | Model |
Stylesheet | .xsl | View |
Schema | .xsd | Controller |
The <request>
element has always the attribute
type="open"
, while the <data>
elements,
which are children of the <request>
elements,
have the attributes type="xml|xsl|xsd"
, respectively.
For each of these requests, Xopus expects the "right" responses
from the server. These responses are always enclosed in
<response>
tags, and should have the same id
as the requests, and an attibute status="ok"
. In case of an error,
the status attribute will be set to "error" and return an error
message.
After the formal definition of the "open file" dialog, there is a (still somewhat generic) example to demonstrate the use of this interface.
Here, we are defining the xml structure of the dialog between Xopus and the server for opening a file for editing. We have 3 requests, and 3 corresponding responses, that have to be exchanged in this order:
The structure of these requests and responses is defined as:
Request messages (Xopus to Server)
<request
type="open"
id="req_path/filename_id">
<data
type="xml|xsl|xsd" <!-- One request for each type of data -->
id=path/filename>
</data>
</request>
Response messages (Server to Xopus)
<response
id="req_path/filename_id" <!-- Same id as the request -->
status="ok" <!-- If no error occured -->
type="open" <!-- Same type as the request -->
xmlns:xlink="http://www.w3.org/xlink"> <!-- This is probably optional??? -->
<data
id=path/filename <!-- Same id as the request -->
type="xml|xsl|xsd"> <!-- Same type as the request -->
Content of path/filename
</data>
</response>
When everything goes well, i.e. no errors occur, the exchange between Xopus and the server looks like the following example:
Xopus (Request 1):
<request
type="open"
id="req_somepath/somedoc.xml_someid">
<data
type="xml"
id="somepath/somedoc.xml">
</data>
</request>
Server (Response 1):
<?xml version="1.0" encoding="utf-8"?> <!-- This is probably not needed -->
<response
id="req_somepath/somedoc.xml_someid"
status="ok"
type="open"
xmlns:xlink="http://www.w3.org/xlink">
<data
id="somepath/somedoc.xml"
type="xml">
<Root> <!-- Start of the requested file's content -->
...
...
... <!-- Content of the xml file -->
...
...
</Root> <!-- End of the requested file's content -->
</data>
</response>
Xopus (Request 2):
<request
type="open"
id="req_somepath/somestylesheet.xsl_somenewid">
<data
type="xml"
id="somepath/somestylesheet.xsl">
</data>
</request>
Server (Response 2):
<?xml version="1.0" encoding="utf-8"?> <!-- This is probably not needed -->
<response
id="req_somepath/somestylesheet.xsl_somenewid"
status="ok"
type="open"
xmlns:xlink="http://www.w3.org/xlink">
<data
id="somepath/somestylesheet.xsl"
type="xsl">
<xsl:stylesheet version="1.0" <!-- Start of the requested stylesheet's content -->
xmlns:xlink="http://www.w3c.org/xlink"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
...
...
... <!-- Content of the stylesheet -->
...
...
</xsl:stylesheet> <!-- End of the requested stylesheet's content -->
</data>
</response>
Xopus (Request 3):
<request type="open"
id="req_someschema.xsd_someotherid">
<data type="xsd"
id="someschema.xsd">
</data>
</request>
Server (Response 3):
<?xml version="1.0" encoding="utf-8"?> <!-- This is probably not needed -->
<response id="req_someschema.xsd_someotherid"
status="ok"
type="open"
xmlns:xlink="http://www.w3.org/xlink">
<data id="someschema.xsd"
type="xsd">
<Schema xmlns="urn:schemas-microsoft-com:xml-data"
xmlns:dt="urn:schemas-microsoft-com:datatypes"
xmlns:xlink="http://www.w3c.org/xlink">
<AttributeType dt:type="string" name="Id"/>
<AttributeType dt:type="string" name="Name"/>
<AttributeType default="URL" dt:type="string" name="href"/>
<ElementType content="eltOnly" model="closed" name="Bericht">
<group order="seq">
<element maxOccurs="1" minOccurs="1" type="Meta"/>
<element maxOccurs="1" minOccurs="1" type="Content"/>
<element maxOccurs="1" minOccurs="0" type="WeiterfuehrendeLinks"/>
</group>
</ElementType>
<ElementType content="eltOnly" model="closed" name="Meta">
<group order="seq">
<element maxOccurs="1" minOccurs="1" type="ErscheinungsDatum"/>
<element maxOccurs="1" minOccurs="1" type="ZeitungsRessort"/>
<element maxOccurs="1" minOccurs="1" type="OnlineRessort"/>
</group>
</ElementType>
...
...
... <!-- Further definitions skipped to improve readability -->
...
...
</Schema>
</data>
</response>
Error (Request for an xml File):
When the xml-file is already checked out by another user, the response looks like :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="16">
<title>You are not allowed to edit this document right now. </title>
<message>"User 'Lala' started working on it on Wed Jun 19 14:22:02 </message>
</error>
</response>
Error (Bad data type requested):
When the data type isn't one of xml, xsl or xsd:
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="2">
<title>No such Type. </title>
<message>data type </message>
</error>
</response>
Error (All Requests):
When the identity of the user isn't defined, the response looks like :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): Unable to get identification from session, check cookies and user! </message>
</error>
</response>
When we couldn't detemine the filename for request :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): Unable to determine filename for request </message>
</error>
</response>
When the file doesn't exist:
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="4">
<title>No such File. </title>
<message>file </message>
</error>
</response>
An other error occurs
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="3">
<title> File file exists, but an internal error occured. </title>
<message>exception message </message>
</error>
</response>
At the end of the editing session, when the user clicks on "close", Xopus places a single request containing the new contents of the edited xml file. As the stylesheet and the schema are not modified during editing, there are no requests for the updating of these.
Again, here is the interface definition and an example for the implementation.
Request message (Xopus to Server)
<request
type="checkin"
id="req_path/filename_id">
<data
type="xml" <!-- Only xml file is checked back in -->
id=path/filename>
Content of the editor (current state of path/filename)
</data>
</request>
Response message (Server to Xopus)
<response
id="req_path/filename_id" <!-- Same id as the request -->
status="ok" <!-- If no error occured -->
type="checkin" <!-- Same type as the request -->
xmlns:xlink="http://www.w3.org/xlink"> <!-- This is probably optional??? -->
<data
id=path/filename <!-- Same id as the request -->
type="xml"> <!-- Same type as the request -->
Content of path/filename
</data>
</response>
When everything goes well, i.e. no errors occur, the exchange between Xopus and the server looks like the following example:
Xopus (Request):
<request type="checkin"
id="req_2002/01/17/al/newzzCWKQDEV5-12.nzzoml_1014216332805">
<data type="xml"
id="2002/01/17/al/newzzCWKQDEV5-12.nzzoml">
<Bericht Id="newzz-2002.01.17-al-newzzCWKQDEV5-12">
<id>2002/01/17/al/newzzCWKQDEV5-12</id>
<Meta>
<ErscheinungsDatum>
<Jahr>2002</Jahr>
---- snip ----
</ErscheinungsDatum>
---- snip ----
</Meta>
<Content>
---- snip ----
</Content>
---- snip ----
</Bericht>
</data>
</request>
Server (Response):
<response id="req_2002/01/17/al/newzzCWKQDEV5-12.nzzoml_1014216332805"
status="ok"
type="checkin"
xmlns:xlink="http://www.w3.org/xlink">
<data id="2002/01/17/al/newzzCWKQDEV5-12.nzzoml"
type="xml">
<Bericht Id="newzz-2002.01.17-al-newzzCWKQDEV5-12">
<id>2002/01/17/al/newzzCWKQDEV5-12</id>
<Meta>
<ErscheinungsDatum>
<Jahr>2002</Jahr>
---- snip ----
</ErscheinungsDatum>
---- snip ----
</Meta>
<Content>
---- snip ----
</Content>
---- snip ----
</Bericht>
</data>
</response>
When the file couldn't be checked in because user Lala already checked out the document, the response looks like :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="17">
<title>You are not allowed to check in this document. </title>
<message>"There was a checkout by user 'Lala' at Wed Jun 19 14:22:02 </message>
</error>
</response>
When the identity of the user isn't defined, the response looks like :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): Unable to get identification from session, check cookies and user! </message>
</error>
</response>
When we couldn't detemine the filename for request :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): Unable to determine filename for request </message>
</error>
</response>
This request/response pair performs a temporary save of the file being edited.
From the interface point of view, the only difference to the "checkin" transaction
is the type
attribute, which is set to type="save"
.
Request message (Xopus to Server)
<request
type="save"
id="req_path/filename_id">
<data
type="xml" <!-- Only xml file is saved -->
id=path/filename>
Content of the editor (current state of path/filename)
</data>
</request>
Response message (Server to Xopus)
<response
id="req_path/filename_id" <!-- Same id as the request -->
status="ok" <!-- If no error occured -->
type="save" <!-- Same type as the request -->
xmlns:xlink="http://www.w3.org/xlink"> <!-- This is probably optional??? -->
<data
id=path/filename <!-- Same id as the request -->
type="xml"> <!-- Same type as the request -->
Content of path/filename
</data>
</response>
When we couldn't write the file :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): Unable to write to output file </message>
</error>
</response>
When the file hasn't a root element:
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): data node does not contain an element node </message>
</error>
</response>
When we couldn't detemine the filename for request :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): Unable to determine filename for request </message>
</error>
</response>
This request/response pair performs a spellcheck of the file being edited.
For this transaction, the type
attribute is set to
type="checkspelling"
, and the misspelled words are surrounded by
<span class="spell_error_xopus"> </span>
tags in
the server's response (see example below.
Request message (Xopus to Server)
<request
type="checkspelling"
id="req_path/filename_id">
<data
type="xml"
id=path/filename>
Content of the editor (current state of path/filename)
</data>
</request>
Response message (Server to Xopus)
<response
id="req_path/filename_id" <!-- Same id as the request -->
status="ok" <!-- If no error occured -->
type="checkspelling" <!-- Same type as the request -->
xmlns:xlink="http://www.w3.org/xlink"> <!-- This is probably optional??? -->
<data
id=path/filename <!-- Same id as the request -->
type="xml"> <!-- Same type as the request -->
Content of the editor (misspelled words tagged)
</data>
</response>
When everything goes well, i.e. no errors occur, the exchange between Xopus and the server looks like the following example:
Xopus (Request):
<request type="checkspelling"
id="req_2002/01/17/al/newzzCWKQDEV5-12.nzzoml_1014220920281">
<data type="xml"
id="2002/01/17/al/newzzCWKQDEV5-12.nzzoml">
<Bericht xmlns:xlink="http:/www.w3.org/xlink"
Id="newzz-2002.01.17-al-newzzCWKQDEV5-12">
<id>2002/01/17/al/newzzCWKQDEV5-12</id>
---- snip ----
<Content>
<Head>
<Haupttitel>Hallo Herr Korosec</Haupttitel>
<Untertitel>Geaenderter Untertitel</Untertitel>
<Lead>Geaenderter Lead</Lead>
<Meta>
<Stichwort>ETH</Stichwort>
<Autor>lenya</Autor>
---- snip ----
</Meta>
</Head>
<Text>
<Paragraph>
<Subparagraph>Absatz geaendert von Memo</Subparagraph>
</Paragraph>
---- snip ----
</Text>
---- snip ----
</Content>
</Bericht>
</data>
</request>
Server (Response):
<response id="req_2002/01/17/al/newzzCWKQDEV5-12.nzzoml_1014220920281"
status="ok"
type="checkspelling"
xmlns:xlink="http://www.w3.org/xlink">
<data id="2002/01/17/al/newzzCWKQDEV5-12.nzzoml"
type="xml">
<Bericht Id="newzz-2002.01.17-al-newzzCWKQDEV5-12"
xmlns:xlink="http:/www.w3.org/xlink">
<id>2002/01/17/al/newzzCWKQDEV5-12</id>
---- snip ----
<Content xmlns:xlink="http://www.w3.org/xlink">
<Head>
<Haupttitel>Hallo Herr <span class="spell_error_xopus">Korosec</span></Haupttitel>
<Untertitel><span class="spell_error_xopus">Geaenderter</span> Untertitel</Untertitel>
<Lead><span class="spell_error_xopus">Geaenderter</span> Lead</Lead>
<Meta>
<Stichwort>ETH</Stichwort>
<Autor>lenya</Autor>
---- snip ----
</Meta>
</Head>
<Text>
<Paragraph>
<Subparagraph>Absatz <span class="spell_error_xopus">geaendert</span> von Memo</Subparagraph>
</Paragraph>
---- snip ----
</Text>
---- snip ----
</Content>
</Bericht>
</data>
</response>
When no spell checker is defined :
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): Spell check request received, but there is no spell checker defined </message>
</error>
</response>
When the request type is unknown, the response looks like:
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="5">
<title>The client sent an unknown request type. </title>
<message> </message>
</error>
</response>
When an other exception occurs, the response looks like:
<response
status="error"
xmlns:xlink="http://www.w3.org/xlink">
<error
number="1">
<title>An internal error has occurred: </title>
<message>Caught exception in dispatchRequest(): error message </message>
</error>
</response>
xopus.xsl
(Currently located at
resources/html/scratchpad/xopus/stylesheets
).
The Edit/Open Button can be modified by editing the Javascript function createEditButton within
the script PREFIX/tomcat/webapps/ROOT/xps/xopus/init.js
.
PREFIX/tomcat/webapps/ROOT/xps/xopus
.
PREFIX/tomcat/webapps/ROOT/xps/xopus/init.js
PREFIX/tomcat/webapps/ROOT/xps/xopus/logic/index.js
For the time being it is /lenya/ethz-mat/xopus/XopusInterface
For this purpose, we are sending all requests matching "xopus/**" to a subsitemap,
called xopus.xmap
, where they are first routed through
an action, the XopusHandlerAction
.
The handler is responsible for decoding the attributes of the request and supplying them to the sitemap, and for handling file operations (i.e. saving), when needed. Check out the source code for more info.
Using the request parameters (supplied by the handler), the response
to Xopus is formatted through a generic stylesheet, xopus_resp.xsl
.
To make a page of a publication available for editing with Xopus, follow the example of the Department page of the ETHZ-Mat publication:
main_xopus.xsl
Make a copy of the existing main.xsl
and change the include statement for
root.xsl
to root_xopus.xsl
.
Change the authoring stylesheet for the page to another version. Don't forget to check for the browser first, Xopus works only with IE 5.5 or later!
For an example, look at the Department Authoring snippet, where the
stylesheets/ethz/mat/Department/authoring/main.xsl
stylesheet
is replaced by stylesheets/ethz/mat/Department/authoring/main_xopus.xsl
.
body.xsl
Add the call to Xopus to the element of the page that you want to edit. The easiest way to do this
is to enwrap the portion that you want to make editable in a <div ...>...</div>
statement containing the specific attributes to call Xopus. For example:
<div id_xopus="dept"
xml_xopus="index.xml"
xsl_xopus="Department/Edit/xopus.xsl"
xsd_xopus="department.xsd">
<span class="CONTALBLETITLE">Chairman</span>
<table border="1" cellspacing="0" cellpadding="2">
<tr>
<td><a class="CONTABLELINK" href="">Department</a></td>
<td><a class="CONTABLELINK" href="mailto:{chairman/email}"><xsl:value-of select="chairman/name"/></a></td>
<td><a class="CONTABLELINK" href="mailto:{chairman/email}"><xsl:value-of select="chairman/email"/></a></td>
</tr>
</table>
</div>
The file paths must be relative to the "root paths" for each filetype, as defined in the
xopus.xmap
for the xopushandler
. Also, do not use template calls in this
stylesheet, as Xopus does not seem to handle those well.
For an example, see config/doctypes/schemas/department.xsd
.