19990503 (v 0.44)
james anderson, benno biewer
|
[background on xml] [alternative
"representations" in lisp] |
we have implemented a primitive "processor" in common lisp for data streams serialized according to the "extensible markup language" standard. this document provides a cursory introduction to xml, describes the implemented parsing/processing mechanism for CLOS-based applications, and explains how to use the processor.
the processor is intended both as an extension to the cl-http server and as a stand-alone xml interface. the runtime environment is examined during the loading process to determine if the if http support is already present. if so, then the existing facilities are used and server extenions are generated to support xml.if cl-http is not present, then these extensions are not loaded and only file streams and primtive http streams are supported.
the xml processor reads a marked up data stream to produce a document object which binds definition information and element content. the respective class definitions include support for access to definition and content data and for document serialization.
additional utilities are included to
STANDARD-CLASS
from and to an xml representation.
several demonstration files are included, among them an example
of document and element serialization is included which presents documentation for
several common-lisp data classes (function, generic-function, symbol, standard-class)
as xml or html, depending on the browser capabilities.
|
|
[Top] |
in its role as an "introduction" to xml, this note provides an admittedly cursory treatment of two topics: what xml is and, how xml relates to lisp applications and development. please note, that - especially with respect to xml itself - our goal is just to get you started. there are already numerous documents available on-line about xml, none of which it makes sense to duplicate here. the reader is referred, in particular, to
and to the various links included therein.
the simplest description of xml is, that it is a cross between html and sgml.
html is the notation used to "markup" text for display in a "browser".
sgml is also a markup notation, which in some forms, looks much like html, but, in
general, permits syntax definitions, called "document types", with various
markup forms. html, in its recent versions, is a particular document style in sgml.
xml is a simplified subset of sgml. it permits document type definitions, but limits
the syntax to one resembling html.
xml is intended to be a notation for storing, retrieving, and, in general, communicating
data in a "self-describing" serialized form. the standard specifies a syntax
to "mark up" text data using annotated, or attributed tags so as to denote
sequence and containment relations among data. each application is free to define
its own tags and relations as a document type.
xml is proposed, in particular, as a notation for data to be exchanged between http clients and servers (or, more accurately among any processes capable of operating with URL-specified data resources). the www-consortium is administering the proposal and standardization process. to quote the proposed standard
"The Extensible Markup Language (XML) is a simple dialect of SGML.... The goal is to enable generic SGML to be served, received, and processed on the Web in the way that is now possible with HTML. XML has been designed for ease of implementation and for interoperability with both SGML and HTML."
if the xml elements are chosen from the html document definition, then the documents would look much like html documents. documents are also permitted, which have no definition, so long as all elements are marked with matching open and close tags or with an empty tag, and so long as containment relations are unambiguous.
one might, for example, express the most trivial of relations from the lisp domain as the following xml document:
<cons><car>first</car><cdr>rest</cdr></cons>
the following, also trivial, html document, would also be a legitimate xml document:
<html> <head></head> <body>greetings in xml</body> </html>
in addition to straight-forward markup, the standard also includes special purpose syntactic constructs to represent document definitions. the syntax of these forms has been chosen to be compatible with sgml. they could, however, just as well have been encoded using the same markup forms as the rest of the document.
the present thinking about XML is embodied in a collection of w3 proposals and technical notes concerning the representation and manipulation of "document objects".
XML would appear to be on its way to becoming the standard representation for serialized electronic data.
in practical terms, these collected documents describe
in terms useful for the lisp developer, this means that a single serialization interface - alternative, but equivalent to the standard reader, would suffice to communicate data with any and all of
we're using it as the serialization form to communicate data among a cl-http server and java front-ends. we intend to use it as the media for communication to editors and persistent stores as they become available. it is straight-forward to implement basic support in a common lisp environment. for a small effort, it will be possible to leverage the development efforts which will follow over the next several years to carry the dynamic development and deployment features which lisp offers into wider setting.
|
|
[Top] |
the lisp world is at no loss for alternatives to serialize data or otherwise represent it external to a lisp process. the lisp standard includes at least two means (reader macros and load forms) which can be used to serialize data for archival or to pass it to another process. with suitable meta-object support, the necessary definitions can be specified as an aspect of class definition.
the lisp application community has also been at no loss to develop representations for data and for data manipulation. in most cases (for example, KIF) the standard incorporates the standard lisp reader and thereby depends on equivalent runtime support among a communicating processes. such standards also extend well beyond the scope of xml, to specify protocols for application-level data-exchange and to specify mechanisms for interpreting messages.
xml, on the other hand, is strictly a convention for encoding. it plays a role
analogous to the #(structure-type slot-name slot-value),
and could be substituted for it in applications which share data with foreign application
environments. as an encoding, xml does not concern protocol questions, which, in
the case of a presentation protocol, are relegated to the application domain, and
in the case of transport protocols are left to an underlying transport layer. for
the latter, http is the likely dominant protocol.for the former, remember "it's
not a language, it's an encoding": semantic issues are also left entirely to
the application, whereby a number of "standardized" applications are being
discussed. (see the various w3c submissions
and reports.)
|
|
[Top] |
this collection of files implements a "nonconforming, validating, model-based XML processor". in practical terms, this means that
this version of the processor can parse and process complete xml documents, including
it also includes a provisional pattern matcher for use, for example, as the core of an XSL matcher, and a compiler for element models which can be used to implement validation.
the most significant limitations are
a the next version will address these issues.
the processor reads XML document to produce an internal node tree which represents the node containment relations denoted in the stream and which establishes links to the specified element definitions for reference to model and attribute declarations and to entity definitions for replacement text. if the XML document specifies a source for a DTD, the DTD document is read to produce an internal representations of the declared elements, models, atttributes, and entities.
as an optional step when creating element definitions, the respective model is
compiled to produce a validation predicate. use of the predicates are left to the
'application' either by means of auxiliary (likely :before) constraint methods, for
example on XML-ELEMENT.APPEND-ELEMENT or on (SETF XML-NODE.CONTENT)(t
XML-ELEMENT).
DTD and XML streams are, for the most part, processed identically. a distinction
is limited to two interface functions which read the named respective stream type
and enforce content constraints on the results.
READ-DTD-STREAM (generic-function (stream NAME) DTD)
READ-XML-STREAM (generic-function (stream) XML-ELEMENT)
the additional argument to READ-DTD-STREAM is necessary in order to
specify the root element and the namespace into which the dtd is imported.
additional interface functions are provided to read individual elements, read PCDATA, CDATA, etc. look at "interface.lisp" for descriptions.
the reading and construction process is controlled by numerous parameter bindings. there are, for example, bindings to specify the class of each node to be instantiated. see "global-bindings.lisp" for explanations. these bindings may be changed and /or the respective access functions specialized in order to either
XML-ELEMENT
nodes.
this prototype includes support for the following xml forms. the distinction between
parsing and processin means that the element is either merely read and instantiated,
or that the relations or side effects specified by the standard are implemented.
| element | parsed | processed | comments |
|---|---|---|---|
| <!-- | yes | yes | comments are appended to the parent node. they are bound separate from element children and keyed to the immediately preceeding element. |
| !ELEMENT | yes | yes | element definitions are bound to the parent DTD. the names are required to be of the same package as the DTD. where element references appear in a model, supplementary (non-standard) ELEMENT-REFERENCE nodes are generated to accommodate forward references and to accept instance-specific attributes. |
| !ENTITY | yes | yes | internal and external character, parameter and parsed character entities are supported. the processor diverges from standard behaviour in that it does not enforce the specified context constraints entity references. |
| !NOTATION | yes | no | |
| ![CDATA[ | yes | yes | bound as text to the parent node |
| ![INCLUDE[ | yes | yes | read as a string and reparsed. the last element in the stream is returned. |
| ![IGNORE[ | yes | yes | read as string and discarded |
| ?XML | yes | yes | processed to bind the standalone declaration, but without support for encoding |
| ?NAMESPACE | yes | yes | this processing instructions is not a part of the xml standard. on the other hand, it would be hard to manage complex documents without some means to define and select namespaces, so we adopted one. namespaces are implemented through packages. the standard lacks a means to specify that a package is to be known within a given dtd. we use namespace processing instructions to this end. |
| !DOCTYPE | yes | yes | a document type declaration specifies the root element, it can reference the an external DTD and or provide an internal definition |
| &entity; | yes | yes | named entity references are appended to the content of containing elements. methods to retrieve and parse the referenced entity's content are not yet implemented. if they were PCDATA only, the dtd is available through the containing elements dtd-element-reference and the string content could be reread with READ-PROCESS-PCDATA. this should wait, however, until we understand the meaning and uses of notations, since things like external entities and binary data aren't that simple. |
| %entity; | yes | yes | wherever they are permitted (type names, models, attributes, ... ?), parameter entities are supported by concatenating streams. the entity value is prepended to the active stream in place of the entity reference. this means that syntactic restrictions specified by the standard for entity values are not enforced. |
| element | yes | yes | elements are parsed and processed. the processing step appends an element to its
parent node. attributes are parsed and bound to the element node. limited attribute normalization is not supported. empty elements are supported. |
|
|
[Top] |
the implementation (version 0.44 and successive) takes the form of a recursive-descent parser.
the control-tree comprises successive layers of
read-production
production-reader-macro
reduce-production
each of these functions comprises methods specialized on the types specified int he xml standard. the following syntactic xml forms are recognized implemented in as objects with parsing and reduction behaviour:
|
|
|
prolog element
Misc* |
|
|
|
|
'<!--' ((Char - '-') | ('-'
(Char - '-')))* '-->' |
|
|
|
|
'<?' PITarget (S (Char*
- (Char* '?>' Char*)))?
'?>' |
|
|
|
|
CDStart CData
CDEnd |
|
|
|
|
'<?xml' VersionInfo
EncodingDecl? SDDecl? S?
'?>' |
|
|
|
|
'<!DOCTYPE' S Name
(S ExternalID)?
S? ('[' (markupdecl
| PEReference | S)* ']' S?)?
'>' |
|
|
|
|
EmptyElemTag |
|
| STag content
ETag |
|||
|
|
|
'<' Name (S
Attribute)* S?
'>' |
|
|
|
|
Name Eq
AttValue |
|
|
|
|
'</' Name S?
'>' |
|
|
|
|
'<' Name (S
Attribute)* S?
'/>' |
|
|
|
|
'<!ELEMENT' S Name
S contentspec
S? '>' |
|
|
|
|
'<!ATTLIST' S Name
AttDef* S?
'>' |
|
|
|
|
'<![' S? 'INCLUDE' S? '[' extSubset
']]>' |
|
|
|
|
'<![' S? 'IGNORE' S? '[' ignoreSectContents*
']]>' |
|
|
|
|
'&#' [0-9]+ ';' |
|
| '&#x' [0-9a-fA-F]+ ';' |
|||
|
|
|
'&' Name ';' |
|
|
|
|
'%' Name ';' |
|
|
|
|
'<!ENTITY' S Name
S EntityDef
S? '>' |
|
|
|
|
| '<!ENTITY' S '%' S Name
S PEDef
S? '>' |
|
|
|
|
'<?xml' VersionInfo?
EncodingDecl S?
'?>' |
|
|
|
|
'<!NOTATION' S Name
S (ExternalID
| PublicID) S? '>' |
|
|
[Top] |
the present implementation is a prototype. we use it to communicate data among an http server and java clients. there are a number of questions, about how it should evolve, for which we as yet have no answers and must gain experience using it together with other parsers and document generators.
the form of interface remains a question. the c- and java-based parser/processor implementations make significant distinctions between an interface concerned with the lexical processing and one concerned with the content. contemporary (as of q1.98, that is pre-dom-implementations) deliberations regarding standard interfaces are directed to so-called "event-based" interfaces. in this form of interface a calling application is informed of the presence of lexical tokens and or the completion of syntax productions through a "call-back" interface, as if they were "events" in the data stream.
such interfaces are significant for applications which intend to filter very large amounts of data in order to operate on a small percentage of the content. in our case such an interface is of little interest. the primary interfaces are for entire document objects. if there should be a need to filter data selectively, one method would be to specialize the element and text classes as well as the functions for processsing or appending elements to implement the "call backs" but not retain the data. either
a stricter processor would require further work to implement the restrictions in terms of the additionalconstriant checks.
the directory "dtd" includes several simple document type definitions. one for lisp "lisp.dtd" and one for XSL patterns "xsl.dtd". the directory "xml" contains small example files. one from microsoft contains a channel description. the the best sources for further examples are net resources:
there are also several test / example files
nb. these latter two are yet untested in this version
in addition to generic elements, this release parses all forms identified by the XML 1.0 recommended standard) (see the XML package in "exports.lisp").
the code is distributed among several dozen files.
there are also several files provided which are specific to run-time support within MCL.the system definition file is "defsystem.lisp". the file "defsystem-xml-records.lisp" concerns an additional modules which provides a uniform interface to xml elements and mcl records.
this prototype is no paradigm of efficiency, it is merely a draft tool for serializing
data for exchange with java "front-end" processes. it is in flux and future
compatibility is not assured. it should be seen as a base for discussion and possible
further implementation only. please do not REdistribute it. it is available from
the cl-http contributed source archive, from which, for the time being, all distribution
should occur.
working with a 2.5M portion of the old testament xml-example file, for instance,
the performance looks like this (mcl 4.1, ppc7300/200):
? (room)
There are at least 13,426,192 bytes of available RAM.
Total Size Free Used
Mac Heap: 1295856 (1265K) 477552 (466K) 818304 (800K)
Lisp Heap: 15453968 (15092K) 12948640 (12645K) 2505328 (2447K)
Stacks: 240368 (235K) 236804 (231K) 3564 (3K)
Static: 5584 (5K) 0 (0K) 5584 (5K)
? (time (let ((*xml-text-class* nil)) ; intern text simply as strings
(defparameter *ot*
(read-xml-stream #P"entwicklung-server:Source:LISP:XML:otxml Folder:ot-abridged.xml"))))
(LET ((*XML-TEXT-CLASS* NIL)) (DEFPARAMETER *OT* (READ-XML-STREAM #P"entwicklung-server:Source:LISP:XML:otxml Folder:ot-abridged.xml"))) took 125,784 milliseconds (125.784 seconds) to run.
Of that, 19,010 milliseconds (19.010 seconds) were spent in The Cooperative Multitasking Experience.
11,065,544 bytes of memory allocated.
*OT*
? (gc)
NIL
? (room)
There are at least 5,853,552 bytes of available RAM.
Total Size Free Used
Mac Heap: 1295840 (1265K) 477552 (466K) 818288 (800K)
Lisp Heap: 15453984 (15092K) 5376000 (5250K) 10077984 (9842K)
Stacks: 240368 (235K) 236804 (231K) 3564 (3K)
Static: 5584 (5K) 0 (0K) 5584 (5K)
?
which is several factors slower than the equivalent c++ parser
several of the references are gathered here in order since, in many cases, a reference includes an alternative link to the respective original document in addition to the documents included with the distribution.
<e1 a1="1"><e2/> and text</e1> "e1" "a1" "1" "e2" "e2" " and text" "e1 e1 and possible content of e2, " and text"
may be constrained by a declaration stipulates content types and/or attribute values.
|
|
[Top] |