As programmers do you long for the old days when data was data and code w=
as code? Do you buy into the idea that the behavior associated with data =
should be embedded within the application so as to
restrict reuse of that data? Ah, the good old days of relational database=
s! In its current usage XML is enabling you to revisit those days again..=
. but don't be persuaded by the dark force! Put on
your OO glasses and see the light!
Sure, XML provides incredible potential, and I am all for it. But in thei=
r current form, XML documents are nothing more than mobile semi-structure=
d non-object databases (this is pretty cool, but not
OO). Why is it that programmers have suddenly forgotten all about objects=
just so they could write XML? Is a return to relational databases that e=
nticing? (Bleech!) The only practical reasoning behind
such an approach is that programmers want to keep their data private. The=
y don't want other applications to have the ability to reuse that data. T=
hey accomplish this feat by embedding all of the code
associated with that data (formally called "behaviors" in the OO era) in =
their own applications. [Who's running this show anyway? Is XML some kind=
of conspiracy to kill OO?]
Here's a simple example. You write an application that converts unformatt=
ed poems into composite poem objects rich with behavior. You want to stor=
e these poems, and share them with other applications
that want to do things with poems (whatever it is you do with poems). You=
define an XML structure and start generating XML documents as a means to=
store and share the poems. Every application
(including yours) that reads in your poems using an XML parser will see t=
he poem as something similar to:
[This XML document was taken from an example accessible at the Microstar =
website (distributors of the AElfred XML parser). The file name is donne=
.xml. Below is the parse tree for this document.]
root |-> Element |-> Element |-> Element
| |-> Element
| |-> Element |-> Element
|
|-> Element |-> Element
|-> Element
|-> Element
|-> Element
Pretty impressive right? It sure doesn't look like a poem object does it?=
Once this structure has been generated every single application will nee=
d to supply its own code to understand how to navigate
and interpret this structure, and provide behavior for it. This is typica=
l if you are a C programmer, but be clear, this isn't OO. And, while DOM =
takes us a bit farther, you still won't get the parser
to produce a poem object and its poem-specific behaviors from the XML doc=
ument (but we still want DOM!).
The process of generating XML strips the behavior out of the objects; or,=
saying it differently, XML and related standards do not describe a mecha=
nism by which one can attach behavior to XML
documents. The parser, in turn, cannot therefore work miracles when it re=
ads the data (which are no longer objects) back into the application. Or =
can it? Why can't we view XML as a serialized object
representation? If we agree that this is not too far fetched, then why ca=
n't parsers deserialize or objectify the objects contained in the XML doc=
uments, rather than simply handing us data and making
the applications do all of the work? What if the parsers generated real =
classes (with behavior!) instead of generic Element classes? The poem abo=
ve would instead look like this: (perhaps if we talked
about XML documents as orders (or anything else) instead of poems it migh=
t be more motivating?)
root |-> poem |-> front |-> title
| |-> author
| |-> revision-history |-> item
|
|-> body |-> stanza
|-> stanza
|-> stanza
|-> stanza
Oh, but could it be that simple? (The answer is "yes.") Would having a pa=
rser output objects with type-specific behavior be useful? (Hmm...) Would=
programmers really want to share their objects if
they could? (The answer should be "yes.") Even if they didn't want to sha=
re their objects, or if nobody wanted their objects, why violate the prin=
ciples of OO and make the programmers' lives more
difficult? Wouldn't it be nice if one could simply tell an object to seri=
alize to XML, and then deserialize back into an object?
With some VERY simple extensions to current parsers this can occur, and a=
lready has -- we've created an extended version of the Lark XML parser wh=
ich provides this capability. Our input to this
extended parser is the XML document and the type-specific classes (like p=
oem) extended with the basic ability to deserialize themselves.
-----------------------------------------------------------------------=
-------------------------------------------------------------------------=
---------------------------------------------------------
=
XML Documents Are Objects!
=
or
=
Killing OO Softly With XML
=
Paul Pazandak
=
Object Services and Consulting, Inc.
-----------------------------------------------------------------------=
-------------------------------------------------------------------------=
---------------------------------------------------------
Introduction
XML documents are indeed objects, or at least they could be. If we simply=
associate behavior with the data structures defined within the XML docum=
ents we could have normal, living, breathing
objects... like we're used to in the programming world. Instead of enabli=
ng the parser breathe life back into our objects, as part of the deserial=
izing or re-objectifying the object, we are forced to
do this within our applications. Simply put, parsers aren't doing enough =
for us.
XML parsers currently support non-portable object specifications. While t=
he XML documents themselves are portable by virtue of being written in XM=
L, the objects represented by those documents are
cannot be objectified without an accompanying document-specific applicati=
on which interacts with the parser.
Current XML parsers provide the ability to parse an XML document, and per=
haps generate a generic object structure (parse tree) corresponding to th=
e document. However, XML documents could potentially
represent more than simple structured documents, they could describe comp=
lex objects with behavior. Common (simple) examples of XML documents incl=
ude address lists. But making use of this information
requires each application which desires to consume address lists to write=
parser-related code, as well as code to implement the behaviors of the a=
ddress lists and their entries. We propose a simple
extension to parsers which would all but eliminate application-parser int=
eraction and the need for document handlers (which do not migrate with th=
e XML document), and would facilitate objectifying XML
documents into type-specific objects (like we're used to having in the pr=
ogramming world) having all related behaviors intact.
Background
Current XML parsers generate generic parse trees (most do anyway). These =
trees represent the structure of the data that was parsed. But what is mi=
ssing is the behavior associated with this data. While
there are methods associated with the generic parse tree elements, these =
are not data-specific but rather generic methods (see the sample code). T=
his approach places the burden on the application to
deserialize the document back into objects using the generic calls and a =
lot of validating code. This is true of all current XML parsers (which su=
pport parse tree generation).
Once the XML document is parsed the information needs to be retrieved by =
the application, so it must access it from the parse tree (if one was gen=
erated -- see the note on problems with event-based
parsing). In general, the consuming application may proceed in one of two=
ways to accomplish this:
* Simple Extraction.
The application will march down the structure, extracting out and co=
nsuming the data as it goes. This requires making calls using the generic=
parse tree methods (parser-specific -- SAX doesn't
support a parse tree API).
* Tree Transformation / Mapping
The application copies the data out of the generic parse tree into t=
ype-specific structures (e.g. Java objects) which contain type-specific d=
efinitions. The data is then accessed by the
application using the type-specific API of these new structures.
In both cases, the application embeds the intelligence of how to access t=
he data within itself. This is not unlike the approach used by relational=
database applications which separates the data from
its behavior. If another application wishes to access this data, it must =
define its own behavior for that data.
An Example
Here's an example to illustrate this. This XML document was taken from an=
example accessible at the Microstar website (distributors of the AElfred=
XML parser). The file name is donne.xml. When an XML
parser generates a parse tree for this document, the resulting (informati=
ve) tree will look like the following in Lark (and similar in the other p=
arsers as well):
root |-> Element |-> Element |-> Element
| |-> Element
| |-> Element |-> Element
|
|-> Element |-> Element
|-> Element
|-> Element
|-> Element
The Element entries are the objects created by XML parser corresponding t=
o the Element Declarations in the XML document. To determine what each el=
ement is, the application must navigate the structure
and inspect each Element object using a generic API. This requires that t=
he knowledge of how to navigate the structure is embedded within the appl=
ication. The interface of this object must be embedded
within the application as well which really violates the object-oriented =
paradigm -- yes, the data is stored in objects, but the associated type-s=
pecific behavior is stored someplace else. While this
may appear similar to how objects are serialized today (without code), th=
e distinction is that any other application that wants to access this obj=
ect will not have access to the code since it is
buried in the application which created it. All other applications will h=
ave to provide their own code (this, again, is how applications for relat=
ional databases are written).
There are several other problems with this approach, not the least of whi=
ch is that the application should not be responsible for doing this. Furt=
hermore, the parser-related code required to walk a
complex structure is complex itself (not quite as complex as code used fo=
r event-based parsing of complex structures however), and is more difficu=
lt to maintain. Finally, the application is forced to
do what the parser has already done, that is understand and navigate the =
structure of the document. The parser has already gone through the entire=
document and generated a structured instantiation of
objects. The crux of the problem is that the parser generates generic obj=
ects which forces all of this additional work on the application. Worse y=
et, there is no reason this has to occur -- nor does
the (tree-generating) parser have to be significantly modified.
Event-based parsing
An alternative to tree generation is simply to consume the structure on-t=
he-fly as it is parsed. This requires writing an XML structure-specific h=
andler (a document handler in SAX terms) which
describes what should happen for each XML declaration that is encountered=
; no structure is automatically generated, so if objectification of the X=
ML document is desired the handler is responsible for
this. Using event-based parsing the application could adopt either of the=
above two approaches, the first being simple consumption and the latter =
which would cause the construction of some structure
corresponding to the XML document. In both cases, at least for complex XM=
L structures, there would be a lot of conditional segmented code which is=
more difficult to write and modify when changes in
the XML structure occur. Using the extension proposed the majority of the=
work is done by the tree-generating parser, empowering the application t=
o see XML documents as objects and alleviating their
burden of using event-based parsing.
Granted, when an application will only encounter one kind of XML structur=
e, event-based parsing might be a reasonable approach from the standpoint=
that only one handler would need to be written. But
it still suffers from some of the same problems as generic parse tree gen=
eration (see the summary section).
XML Parsers Extended
What if the output of the parser was a type-specific structure which coin=
cided with the definition of the structure in the XML document? And, what=
if that resulting objects contained the type-specific
behavior for the specific element type parsed? What if the resulting pars=
e tree for the example above instead looked like:
root |-> poem |-> front |-> title
| |-> author
| |-> revision-history |-> item
|
|-> body |-> stanza
|-> stanza
|-> stanza
|-> stanza
where poem, front, body, title, author, revision-history, and stanza were=
all classes with type-specific behavior? Instead of writing something li=
ke the following to retrieve the title of the poem:
Element front =3D null;
Vector v =3D root.chilren();
if (v !=3D null) {
Element front =3D v.elementAt(0); // v(0) "should" be the front eleme=
nt, we hope
if (front !=3D null)
v =3D front.children();
for (i=3D0; i < front.size(); i++) {
Element child =3D v.elementAt(i);
if child.type().equals("title")
return child.content();
}
}
}
return null;
one could simply write:
poem.getTitle();
More importantly, all of the behaviors that should be associated with eac=
h of these object types would be defined as part of the object interfaces=
themselves rather than embedded within the
application.
Granted, an application can generate this same structure using the transf=
ormation / mapping technique above. However, this is partially a duplicat=
ion of effort since it requires the application to
navigate the structure generated by the parse tree, and then generate a n=
ew structure which mirrors the parse tree. The extension to Lark eliminat=
es the need to do this because it instantiates the
correct type-specific parse tree the first time. Note that this is an ext=
ension to Lark, and therefore applicable to any XML document.
Details
What occurs in the underlying implementation of an XML parser is rather s=
traightforward. When it sees an XML element declaration, it instantiates =
a generic Element object (with Element only related
methods). The extension to Lark simply extends the behavior of the parser=
so that instead of instantiating generic Element objects, it instantiate=
s type-specific ones.
So when the parser encounters a new element declaration, it looks for a c=
lass declaration which identifies which class to instantiate in lieu of a=
generic Element class object (where it looks is
described below). For example, when the parser identifies the "poem" elem=
ent declaration, it looks for a class declaration for poem. If it finds o=
ne, it instantiates an object of that class rather
than a generic Element object. The poem class extends the interface of th=
e Lark Element class, but in addition, adds type-specific methods relevan=
t to a poem object.
Within a type-specific parse tree class, like poem, is code which underst=
ands how to extract the parsed information. In effect, the object underst=
ands how to investigate itself. This code is provided
by the object type creator. It will travel with the object as a means to =
facilitate re-objectifying the XML back into an object. This enables reus=
e of the object by any application. Of course, as
stated above, the poem class will also provide a poem-specific interface.
A method I have added to the Element class is process(). It can be called=
once an element has been parsed. In each implementation, for example wit=
hin the poem class, the process() code handles
extracting the data from the inherited generic structures of the Element =
class. Alternatively, poem methods could simply be written that do this d=
irectly. But, it is important to note that the object
itself is doing this, and further, that no other parse trees or duplicate=
structures are being constructed.
The location of the class declaration is not hard-coded. It could be with=
in the XML file itself, in a DTD, in a stylesheet, or in a remote reposit=
ory, for example. In addition, local class
declarations may be used to override default class declarations. In the i=
mplementation of the Lark extension, I have simply embedded them in the D=
TD file along with the declaration of the structure of
the XML file. In its current form the class declaration would look like t=
he following for the poem example above, although there would be many way=
s to accomplish this:
<!ENTITY Poem-Class "http://www.objs.com/xml/poem/com.objs.ia.specificati=
on.xml.poem">
<!ENTITY Front-Class "http://www.objs.com/xml/poem/com.objs.ia.specificat=
ion.xml.front">
<!ENTITY Body-Class "http://www.objs.com/xml/poem/com.objs.ia.specificati=
on.xml.body">
...
<!ENTITY ClassSuffix "-Class">
The ClassSuffix is used to avoid possible naming collisions (which may be=
solved otherwise using the XML namespaces proposal). So, when a new ele=
ment declaration is identified by Lark it inspects
this list looking for an entry matching the pattern <element type><ClassS=
uffix>, or in the case of the poem element declaration, "Poem-Class".
Cavaet Language?
Is this a language-specific extension? Not really. The class declarations=
could be (for example) written in Active-X I suppose, or even wrapped in=
CORBA, thereby enabling any language to take
advantage of the idea of XML documents as objects. It would up to the par=
ser to find the correct class declaration and objectify accordingly.
Implementation Experience
My experience with XML parsers began last year. As part of a DARPA-funded=
project I am implementing an architecture to demonstrate scalable object=
service architectures. I started using event-based
parsing as a means to import object service specifications. These XML spe=
cifications represent real (Java and CORBA) services that are invoked by =
the architecture.
I noticed that by adopting an event-based approach to parsing I would hav=
e to write a lot of code which would be difficult to maintain should I ha=
ve changes in the future. In addition, this code would
be hard for someone else to understand since each parser callback method =
would include conditional statements for several types of elements, and t=
he code would be spread across several methods. I
prefer a clean separation of code whenever possible, and this didn't seem=
very clean.
I decided that tree parsing was a more practical route. The parser would =
automatically generate a structure for me. But, then I realized that I ha=
d to write all of the code to navigate this generic
object structure, pull out the information I wanted, and then copy it int=
o service specification objects having the behavior I wanted.
Since the parser was already generating classes, why not just tell it to =
generate the real classes to begin with? The classes themselves would ha=
ndle deserialization. Sounds like OO to me! With
modest changes to Lark, when it sees an XML service specification documen=
t it will generate service specification objects right away. This extensi=
on will work for any XML document which defines
specializations of the Element class and makes them available to the pars=
er. Besides asking Lark to parse the document, my application has no othe=
r parser-related code. Furthermmore, any other
application can use my XML service specification documents, and load them=
in as service specification objects with only a few lines of code.
Summary
In summary, an extension has been presented which extends the capabilitie=
s of Lark, but which could be applied to all tree-generating XML parsers.=
It enables type-specific composite object
construction to occur within the parser which is a significant improvemen=
t over generic parse tree construction because:
* We can attach behavior to XML documents.
* We can therefore treat XML documents as objects.
* It eliminates most of the neccessity of the application to understan=
d SAX, or parser-specific structures, as well as reducing the amount of d=
irect interaction between the application and the
parser. To a certain extent DOM will accomplish this, but the extens=
ion proposed here augments this by enabling the generation of type-specif=
ic interfaces.
* The application is then free to interact with the generated objects =
as "real" objects having type-specific structure and behavior.
* More importantly, the XML documents can roam freely (likened to seri=
alized objects) which can be objectified again by any application. This w=
ould not be possible with generic tree parsing or with
event-based parsing (which requires specialized structure-specific p=
arsing handlers).
If we view XML as a means to serialize an object, we should view the pars=
er as the mechanism to deserialize (or objectify) it. Once we convert an =
object to an XML representation, it simply doesn't
make sense to throw away its behavior or the code which understands how i=
t should be deserialized. Embedding this knowledge within an external app=
lication is just revisiting the relational DBMS
experience and ignores the principal benefits of object technology.
If this proposed extension were adopted it would benefit significantly fr=
om a standardization of the Element interface (something that will happen=
with DOM). In this way, the associated class files
would not be parser-specific, and therefore any XML document could be obj=
ectified by any tree-generating parser.
Status
I anticipate that the extensions I have made to Lark will be incorporated=
into a next version of Lark (I assume this from previous dialogues I hav=
e had with Tim Bray). If not, and in the meantime, the
enhanced version of Lark is freely available on request.
References & Acknowledgements
Related work in this area is described in Towards a Web Object Model by F=
rank Manola, Object Services and Consulting, Inc. Thanks to Frank Manola =
(OBJS, Inc.) and Tim Bray (Textuality, Inc.) for their
useful feedback.
-----------------------------------------------------------------------=
-------------------------------------------------------------------------=
---------------------------------------------------------
This research is sponsored by the Defense Advanced Research Projects Agen=
cy and managed by the U.S. Army Research Laboratory under contract DAAL01=
-95-C-0112. The views and conclusions contained in
this document are those of the authors and should not be interpreted as n=
ecessarily representing the official policies, either expressed or implie=
d of the Defense Advanced Research Projects Agency,
U.S. Army Research Laboratory, or the United States Government.
=A9 Copyright 1998 Object Services and Consulting, Inc. Permission is gra=
nted to copy this document provided this copyright statement is retained =
in all copies. Disclaimer: OBJS does not warrant the
accuracy or completeness of the information in this document.