How to cite this paper
Rennau, Hans-Jürgen, and David A. Lee. “XDML - an extensible markup language and processor for XDM.” Presented at Balisage: The Markup Conference 2011, Montréal, Canada, August 2 - 5, 2011. In Proceedings of Balisage: The Markup Conference 2011. Balisage Series on Markup Technologies, vol. 7 (2011). https://doi.org/10.4242/BalisageVol7.Rennau01.
Balisage: The Markup Conference 2011
August 2 - 5, 2011
Balisage Paper: XDML - an extensible markup language and processor for XDM
Hans-Jürgen Rennau
Senior programmer
bits - Büro für Informations-Technologie und Software GmbH
Hans-Jürgen Rennau works as a software developer for bits GmbH (Büro für Informations-Technologie
und Software). He takes a keen interest in the integration of object-oriented and
“item-oriented” (XML) components of behavior and components of information. Hans-Jürgen's
background as a biologist partly accounts for his belief that the naturalness of a
thought is important to its potential. A natural integration of two natural approaches
— OO and XML — is what he strives for in theory and practice.
David Lee
Senior Principal Software Engineer
Epocrates, Inc.
David Lee has over 25 years experience in the software industry responsible for many
major projects in small and large companies including Sun Microsystems, IBM, Centura
Software (formerly Gupta), Premenos, Epiphany (formerly RightPoint), WebGain, Nexstra,
Epocrates. As senior principal software engineer at Epocrates, Inc., Mr Lee is responsible
for managing data integration, storage, retrieval, and processing of clinical knowledge
databases for the leading clinical information provider.
Key career contributions include Real-time AIX OS extensions for optimizing transmission
of real-time streaming video (IBM), secure encrypted EDI over internet email (Premenos),
porting the Centura Team Desktop system to Solaris (Gupta, Centura), optimizations
of large Enterprise CRM systems (Epiphany), author of xmlsh (http://www.xmlsh.org)
an open source scripting language for XML.
Copyright © 2011 by the authors. Used with permission.
Abstract
XDML is a set of rules how XDM values can be built which are more
useful entities as compared to ordinary XDM values. The key idea is to insert
into the XDM values control information which guides the interpretation and
processing of the data. In particular, it structures the XDM value into
named parts and associates these parts with metadata. The control
information is evaluated by an XDML processor, which reports and processes
the data accordingly. The processing of a part is organized as the execution
of operations which the control data bind to the part, but whose actual
invocation depends on API calls of the XDML user. The bindings are
represented by request messages which encode the actual input to operations
selected from an extensible library of available "XDML operations".
The operation bindings of a part can be regarded as a specific interface
dynamically attached to the data of the part. The net result
of this approach is to enable the creation of self-describing XDM values: they encode
the way how they are presented to applications, as well as how they
should or might be processed. This means that the
XDM producer - e.g. XQuery programs - can emit "rich" data whose downstream
processing is significantly simplified.
Table of Contents
- Introduction
- Why ask for XDM (if we have XML)?
- XDM structure
-
- Partitioning an XDM value
- Imposing tree structure
- Concept: Information units
- XDM metadata
-
- Why and how add metadata?
- A model of metadata
- XDML - the concept
-
- Goals
- Structure model
- Metadata model
- Processing model
- Encoding principles
- XDML - concrete proposal
-
- XDML operations
-
- Data model of input and output
- Request messages
- Special parameter values
- Library of standard operations
- Extensibility
- Methods
- Execution context
-
- Execution context "finalize"
- Execution context "execute"
- Execution context "enable"
- Execution context "translate"
- Method definitions
- XDML user perspective
-
- Obtaining and extending the XDML processor
- Obtaining an XDML value
- Parsing an XDML value
- Processing an XDML value
- Example
- Generalization: XDML as an information model
-
- Encoding XDML with map items
- Encoding XDM as XML
- Discussion
Introduction
XDM [W3C XDM] is the data model of the major XML processing languages – XPath, XQuery
and XSLT. The model is marked by a bold simplicity: (a) every value is a sequence
of items,
(b) an item is either an XML node or an atomic value, (c) there are seven kinds of
XML
nodes and (d) a few dozens atomic types. This means that the size and complexity
of an
XDM value is virtually unlimited, and at the same time that any value can be decomposed
into a linear sequence of building blocks, the items. "XDM item" is an abstraction
enabling
us to regard a single byte and a huge XML document as just two instances of the same
building block.
One can look at the XDM from three different perspectives. The first one regards XDM
as a
component of those processing languages, concerning only writers of XPath expressions,
XQuery scripts or XSLT stylesheets. We suspect that the majority of software developers
and architects would subscribe to this view.
The second perspective takes into account that input and output of those languages
is
also XDM and accepts the XDM as a player in the game of process integration. This
perspective pays attention to the issue of translating information back and forth
between XDM values and other data models, for example the data models of general
purpose programming languages. It should also take an interest in the
serialization of XDM values.
A third perspective makes a step from looking at the XDM as either a local affair
of specialized languages or a challenge for data mapping. This new perspective regards
the XDM as the foundation for building a new kind of resource, offering some particular
advantages in comparison to other resource types – e.g. XML documents, relational
tables
or CSV files. At the same time it gives a boost to XQuery, as XQuery
is the XDM producer par excellence. Increased importance of XDM means increased importance
of XQuery.
Ironically, the key step toward a new appreciation of the XDM is awareness of its
fundamental limitation: there is no structure – only a flat sequence of items; there
is no meta information – only items and nothing else. An XDM value has something in
common with a string – no limitation of size and complexity, but unless a creative
step is taken there is no general way how to impose and detect a structure (above
the level
of its building blocks, that is).
Concerning strings, the creative step was the invention of markup: divide the sequence
of atoms (characters) into sections of primary information and those of meta information,
the latter also known as markup. One might consider doing something equivalent with
XDM
values, where the atoms are XDM items, rather than characters. We want to explore
the
potential of such an approach. Based on prior experimental work, we propose
a simple markup language and an infrastructure evaluating it.
A prototypic reference implementation is a work in
progress, and our main intent is to open a discussion.
Why ask for XDM (if we have XML)?
Let us assume a consumer’s perspective. Scenario: some processing
yields a result. This might be an XML document, a sequence of XML documents,
or an XDM value. The last alternative is clearly the most general one, as
any sequence of XML documents is an XDM value. But do we really need this
alternative, if we consider the expressiveness of XML?
From a theoretical point of view, the answer is "no": whatever you can encode as an
XDM value you
can translate 1:1 into an equivalent representation consisting of a single
XML document. For example, the following rules would suffice: (a)
the XDM items are represented by children of the document element; (b)
a dedicated type attribute on these children encodes the item type.
Clearly - XDM values cannot express more than a
single XML document, if some simple conventions are accepted.
We turn to the practical side and consider the
usage of the results.
Can XDM under certain circumstances provide more convenient access to the
units we need, or can it deliver units which are a closer fit to
what is actually needed?
Atomic values
A striking difference between XML and XDM is that the latter supports
atomic values. This is a concrete advantage: if the desired result
is one or several atomic values, then XDM can explicitly deliver
them as such, whereas in the case of an XML result they must be
extracted. Extraction requires knowledge about the result document
structure and involves non-trivial instruments like
an XPath or DOM API. A further drawback of the XML variant is
computational overhead. Conclusion: in cases where the result
consists wholly of atomic values, XDM is probably the more
suitable format.
Collection-like data
The second difference between XML documents and XDM values is that documents are
logical trees within which everything is
related to everything; whereas an XDM
value is a collection of independent entities.
What if the result is just that,
conceptually, a collection? Then the main concern is fast and convenient access
to the individual parts, as well as the possibility to process them – e.g.
update them – in safe isolation. Typical examples for collection-like results are:
-
a heterogeneous result, the parts of which are used in different ways
-
a large result, only selected parts of which are used
So the need for differential or selective processing calls for a collection-like
result. Arrays and maps come to mind, supporting index or name based access to
self-contained units. As we have seen, it is easy to mimic
collections with XML documents. This amounts to an "XML-as-a-container" approach.
Under many circumstances, this may be a perfect solution. But there are issues
that may become important:
-
the access to parts is XPath-based, rather than name- or index-based
-
the whole result tree must be constructed in memory (unless streaming processing is
used)
-
local modification of the result means updating a large document
XPath-based access is inconvenient, compared to name- or index-based access. It may
also be less efficient. The need to construct the whole result tree is a real drawback
if such a construction is not required for other reasons
anyway. This must not be the case. If the result is available in serialized form,
then it makes a big difference if the whole result must be turned into an
in-memory tree, or if small, independent parts can be located and selectively
expanded. And the required parsing may be extremely fast if the parser is
able to locate the desired parts without parsing the details of the preceding parts.
Is XDM a good alternative? Not or not yet. The lack of structure and metadata turn
XDM into an awkward format: it resembles a Java array of type Object[]
.
And there
is not yet a serialization format available, let alone a parser to read such a
format. If XDM is to excel as a collection-like format, these problems – no
structure, no metadata, no serialization – would have to be solved.
Updatable result
In pipelined processing, it is a common requirement to receive the result of a
preceding step, modify it locally and pass it on to the next step. If the result
is a collection of self-contained parts, such local updating is easier in several
aspects, compared to the updating of a monolithic document. XDM looks promising
for such purposes, but the difficulty of selective access – no structure, no
metadata – reduces the attractiveness.
Continuous result
Some resources grow continuously by appending more data. Log data are the classical
example. Such data, as any other data, may be desired to be XML, so as to enable
XML processing. But continuous resources must not be an XML document, as it is impossible
to
append data to a document, they must be inserted, which is much more difficult.
In this case, XDM (a lossless serialization provided) is an obvious solution,
as you can append items to an XDM value without difficulty.
Result as an XDM provider
XDM is the input format for XPath, XQuery and XSLT. In pipelined processing, one
step might produce a result which provides XDM input for another step – either
the value as a whole is used, or one or more subsequences of it. In this scenario,
an XDM result is convenient and natural. Dependent on the type of the required
input XDM , an XDM result may be a better alternative than an XML result.
We draw a conclusion:
XML documents should not be the only option for encoding the result of XML
processing. No native representation of atomic values, the tight coupling implied
by overall tree structure and the inability for plain appending must not be ignored.
XDM is an interesting alternative, as it is a superset of XML and
addresses those issues. But XDM is, as we said, an awkward format due to lack
of structure and metadata. Thus we came to explore the possibility of
augmenting XDM: add to it control information
which imparts structure and enriches the data with metadata. The goal is to
combine XDM’s built-in advantages – support for atomic values, collection-like
nature, being appendable and being a natural XDM provider – with structure and
metadata enabling convenient and guided access to the contents, as well as
simplified processing.
XDM structure
Partitioning an XDM value
Consider the situation that an XDM value should convey two code lists, each one
represented by a sequence of string items. XDM offers no way to tell where one
list ends and the other begins. Similar example: the XDM value is a sequence of
XML documents which represent the log data gathered during one hour - how to
identify the subsequence corresponding to one day of operation?
A quick and simple solution is to insert into the XDM
value additional items which delimit subsequences. These items can be regarded
as control items, to be distinguished from the
original data items. The subsequences are parts of the XDM value which have been
turned into new units of information. In order to give names to these parts,
we add a "name" attribute to the respective control item. Example:
<xm:part xmlns:xm=”http://www.xdml.org/ns” name=”alpha-codes”/>,
a001,
a005,
a012,
<xm:part xmlns:xm=”http://www.xdml.org/ns” name=”beta-codes”/>,
b002,
b003
And if the uniqueness of part names is not guaranteed, an optional "partID"
attribute may accompany the mandatory "name" attribute.
Imposing tree structure
The shown use of control items defines parts of an XDM value in an intuitive way:
the contents of a part is simply all items following the part definition and
preceding the next part definition, or all following items, if this was the last
part definition. But we might also allow "complex parts" - parts containing
parts, to be distinguished from simple parts which contain only data items. To
encode this structural model, we choose a simple rule: the contents of a complex part
ends before an item explicitly "closing" the part, whereas the contents of a
simple part is delimited implicitly: it ends before the next control
item defining a new part (simple or complex) or closing the surrounding complex
part. Note that these parts - simple or complex - are defined in a "streaming"
fashion - contents are not children, but a subsequence of items delimited by
an item recognized as start point and another item explicitly or implicitly
meaning an end point (or the end of the XDM value, as a special case).
In order to keep things simple, we constrain the definition of complex parts:
they must not contain data items outside of contained parts. In other words:
parts must not be mixed, their content is either a sequence of data items,
or a sequence of parts which may be simple or complex. An example using
complex parts:
Note: Leaving out namespace declarations
For brevity, all further examples will leave out the namespace declaration xmlns:xm=”http://www.xdml.org/ns".
<xm:complexPart name="code-lists"/>,
<xm:part name="alpha-codes"/>,
a001,
a005,
a012,
<xm:part name="beta-codes"/>,
b002,
b003,
<xm:complexPartEnd/>,
<xm:complexPart name="logs"/>,
<xm:part name="log0800" />,
<log>...</log>,
<xm:part name="log0900" />,
<log>...</log>,
<xm:complexPartEnd/>
XDML - the concept
By now we have collected a set of ideas which can be assembled into
a comprehensive concept how XDM is turned into a
language designed to encode
information content as well as information processing.
XDM is turned into a language by defining
and constraining the way how control items can be used within an XDM value.
To denote this language we use the acronym "XDML" (short for:
"XDM markup language"). An XDML value is then an XDM value which uses control
items in a way consistent with the rules of the language.
We distinguish between the concept of an
XDML language and a concrete specification of the language. While we
offer a first proposal for such a specification, we attempt to factor
out basic principles. These principles should be simple and
intuitive to a degree which a concrete elaboration cannot attain.
Note: Informal style
For the sake of readability, we do not embark
on any formal definition. Rather, we want to convey the definition in a
natural style which concentrates on ideas and intent at the expense of formal
exactness and completeness.
Goals
XDML is a set of rules how XDM values can be designed in order to become more
useful entities as compared to ordinary XDM values. The key idea is to insert
into the XDM values control information which guides the interpretation and
processing of the data. An XDM value thus augmented is called an XDML value.
Its usefulness is provided by an XDML processor, which
is a generic program evaluating the control information.
XDML addresses the
following major goals:
-
to structure XDM values into nestable parts
-
to enable name-based access to XDM parts
-
to associate XDM parts with metadata
-
to process XDM parts as guided by their metadata
Structure model
XDML structures XDM values by grouping
the XDM items. The resulting groups are units of usage in a broad sense: conceptual
units of
information, units of data retrieval and units of data processing.
Item groups are called information units.
The grouping approach distinguishes:
and introduces the following constraints:
Processing model
XDML values are submitted to an XDML processor
which evaluates the control information and is responsible for reporting
and processing the data
accordingly. The processor is viewed as the sum of two components:
-
an XDML parser
-
XDML engine
An XDML parser delivers the information encoded as
XDML value in a structured way. The engine enables other kinds of
processing. A concrete specification of XDML must define a
processing model governing the engine and its control by
metadata and user actions (API calls).
Encoding principles
XDML defines the syntax and semantics of control information embedded in
XDM values. We propose four general encoding principles:
-
control information is encoded by control items, to be
distinguished from data items
-
a control item is an XDM item which is an element information
item in a particular namespace
-
each information unit is associated with a control item defining
the unit in terms of metadata
-
metadata components are not mixed - each component is encoded
by a distinct (possibly empty) set of elements
A concrete specification of XDML must elaborate these principles into a
concrete encoding model. This model must define the names and structure
of control items, and it must define the mapping of control
items onto content items ("where does the unit begin and end?").
XDML - concrete proposal
The step from XDML as a concept to a concrete specification requires:
-
A concrete encoding model
-
Specification of an XDML parser
-
Specification of a processing model
Note: On language binding
The XDML user communicates with the XDML processor via an API.
A processor implementation is therefore
bound to a programming language, whereas the concept of an XDML processor
is language neutral. Our ongoing implementation work uses Java,
and API code snippets in this paper use Java as well. This representation
is chosen for convenience sake and does not mandate Java in
preference to other languages.
Encoding model
We adopt the rules applied in our illustrative examples:
-
Control items contain elements in the XDML namespace:
http://www.xdml.org/ns
-
Simple information units are preceded by an <xm:part>
item
-
Complex information units are delimited by <xm:complexPart>
and
<xm:complexPartEnd>
items
-
Name and partID of an information unit are given by the
"name" and "partID" attribute of an <xm:part>
or
<xm:complexPart>
item
-
Descriptive metadata are encoded as attributes or child
elements of an <xm:part>
or
<xm:complexPart>
item; they
must be in a namespace but must not be in the XDML namespace
We extend the model of
<xm:part>
items by three further
standard attributes. Attribute "private", if containing the value "true",
indicates that the unit is used to assist in the processing of other units
and should be ignored by the XDML user. Two other attributes convey type information
and
thus facilitate the translation of XDM values into the data model of the processor
language:
Finalization is a processing which is part of the proposed
processing model and which may change the data type of the unit (see
section “Execution context "finalize"” for
details). The following example shows two information units containing
a sequence of nodes and a string, respectively, as indicated by the type attributes:
<xm:part name="logs" type="nodes"/>,
<log>...</log>,
<log>...</log>,
<log>...</log>,
<xm:part name="query_getSummary" type="string" private="true"/>,
xquery version="1.0"
...
XDML parser
The parser has to report data in accordance to a data model which in turn
depends on the processing model. Therefore the parser will be dealt with later,
after explaining the
processing model and in the context of describing the various APIs of the XDML processor.
Processing model
The processing model is based on three concepts which the following
sections will explain in detail:
-
Operation - any processing can be decomposed into distinct operations
-
Method - unit of processing composed of one or more operations
-
Execution context - it specifies when to invoke a method and what to do with
the return value
XDML operations
Data processing provided by the XDML processor is modeled as the execution of discrete
operations,
collectively called XDML operations. XDML operations thus serve as basic unit of data
processing:
an operation is either executed as a whole or not at all; and any processing can be
decomposed
into the execution of one or more operations. An operation is supplied with input
information,
it may produce output information and it may have side-effects. Output information
is the return
value of the operation. Input information comprises a data context and a request message.
The data context can be regarded as the main input,
comparable to the context item of XQuery, the context node of XSLT or the
primary input port of XProc. The data context of an XDML operation is (usually) the
value
of an information unit (as represented by the implementation language of the XDML
processor). Therefore one might say that an XDML operation is applied to an information
unit, or that an information unit is processed by an XDML operation.
The request message consists of named parameters,
comparable to the external variables of XQuery and the global parameters of XSLT.
In the case of XProc, the corresponding input sources would be non-primary input ports,
options and parameters.
The return value of an operation may be an
instance of any type supported by the implementation language of the XDML
processor. Note that this value may or may not have a default mapping to
an XDM value. In other words: operations may produce a result which is not
related to the XDM model, e.g. an object of a custom class.
The XDML provider defines the processing of an information unit by
associating it with methods. A method is a processing defined
as the sequential execution of one or several operations. It is
therefore encoded as one or more request messages and
the choice of a so-called
execution context. The context determines when to invoke the method and
what to do with the return value. Method definition is described in
section “Method definitions”.
The current section describes XDML operations in general terms, independently of
their use in a particular execution context. Main aspects are the data model
of input and output, the encoding of input by request messages, the standard
library of XDML operations and the extensibility by user-defined operations.
Request messages
The XDML provider encodes the input information of an operation by an
element information item representing a request message. This message
is implicitly accompanied by a data context, which is either the value
of the surrounding information unit or the return value of a
preceding operation.
The request message has the following parts:
-
the root element representing the message as a whole
-
attributes encoding statically known parameters of type “string”
-
child elements encoding statically known parameters of type “node”
or “node sequence”
-
an optional child element <xm:params>
representing the dynamic parameters
-
the attributes of <xm:params>
encoding dynamic
parameters of type “string”
-
child elements of <xm:params>
encoding dynamic parameters
of type “node” or “node sequence”
The name of the root element equals the operation name, and the names of
attributes and elements representing parameters correspond to the parameter
names. Consider this example:
<submitToXSLT serialize=”true”>
<stylesheet>
<xsl:transform …>…</xsl:transform>
</stylesheet>
<xm:params verbosity=”1”>
<weatherData><weather>…</weather></weatherData>
</xm:params>
</submitToXSLT>
The operation "submitToXSLT" is invoked with two statically
known parameters (“serialize” and “stylesheet”) and two dynamic
parameters (“verbosity” and “weatherData”). In both
parameter groups there is a string parameter as well as a node parameter.
The operation executes the stylesheet supplied as parameter “stylesheet”
and passes to it two stylesheet parameters, one with name “verbosity” and
type
xs:string
, the other with name “weatherData” and
type
node()
. The
operation also passes to the stylesheet the value of the
surrounding information unit as context node.
Special parameter values
A request message may reference
Parameter values supplied by the XDML user
A request message may reference values supplied by the XDML user. Values
can be supplied as the execution of XDML operations is always triggered
by an API call of the XDML user (see
section “XDML user perspective”). A reference to a
supplied value is encoded by the expression
$arg{argName}
which is resolved to the value of an invocation argument with name
“argName”. For example, the following request message binds two
dynamic parameters, “verbosity” and “weatherData” to values supplied
by the XDML user:
<submitToXSLT serialize=”true”>
<stylesheet>
<xsl:transform …>…</xsl:transform>
</stylesheet>
<xm:params verbosity=”$arg{v}”>
<weatherData>$arg{weatherData}</weatherData>
</xm:params>
</submitToXSLT>
Note that the parameter name used by the request message and the
argument name expected from the XDML user need not be the same:
in the example, the request parameter “verbosity” is bound to
invocation argument “v”. The XDML provider’s choice of referenced
argument names (in the example – “v” and “weatherData”) defines
the “signature” of the operation from the XDML user’s perspective.
Library of standard operations
The XDML processor offers a library of available XDML operations.
The library comprises
See
section “Extensibility” for details about the registration facility. Some examples of
standard operations are:
Table I
Some standard XDML operations.
Operation name |
Description |
createMapFromStrings |
Creates a map object, using as input a sequence of strings read from the data context.
|
createPropertiesFromStrings |
Creates a Properties object, using as input a sequence of strings read from the data context.
|
execAsSQL |
Regards the data context as a sequence of SQL expressions and executes them.
|
execAsPerl |
Regards the data context as a Perl script and executes it.
|
execAsXQuery |
Regards the data context as an XQuery program and executes it.
|
execAsXSLT |
Regards the data context as an XSLT stylesheet and executes it.
|
execAsXProc |
Regards the data context as an XProc pipeline and executes it.
|
readDocument |
Reads a document into a node object, reading the document URI from the data context. |
readTextFile |
Reads a text file into a string, reading the file URI from the data context. |
sendFTP |
Sends the data context per ftp. |
sendSOAP |
Regards the data context as the payload of a SOAP request, sends it
and returns the payload of the response.
|
submitToXQuery |
Executes an XQuery program and passes the data context to it
as context item.
|
submitToXSLT |
Executes an XSLT stylesheet and passes the data context to it
as context node.
|
submitToXProc |
Executes an XProc pipeline and passes the data context to it
as primary input.
|
validate |
Validates the data context with an XML Schema. |
writeDocument |
Stores the data context as an XML document. |
writeTextFile |
Stores the data context as a text file. |
Extensibility
The XMDL processor offers a generic mechanism for extending the library
of XDML operations at runtime. This is achieved by an interface for
registering proprietary operations:
interface XDMLRegistry {
void registerXDMLOperations(XDMLOperations impls);
}
On registration, an implementation must be supplied as an implementation
of the interface
XDMLOperations
. It represents the
invocation of an operation as a method with a generic signature:
interface XDMLOperations {
QName[] getOperationNames();
void execute(OperationRequest requestMsg,
DataUnit dataContext,
DataUnit returnValue)
throws XDMLException;
}
Implementing proprietary operations is a straightforward task:
interfaces
OperationRequest
and
DataUnit
provide access to
operation name, request parameters and data context, respectively.
The return value is inserted into an instance of interface
DataUnit
which is either supplied from without or instantiated within the
implementation.
Methods
In most cases, a desired processing can be provided by a single operation, in
other words: the unit of intended processing matches the basic unit of
implemented functionality. Sometimes, however, a processing may
require two or more operations to be executed. As a generalization, our
processing model defines the unit of intended processing as a sequence
of one or more operations. This unit we call a method.
Assuming sequential execution of the operations,
one may wish for flexibility concerning the data context: shall the second
operation use, like the first one, the value of the information unit, or
shall it use the return value of the preceding operation? This flexibility
is easy to implement, and it is easy to encode:
We introduce an attribute "dataContext" which may be attached to a request message
in order
to encode where the actual data context is found. Rules:
-
attribute missing => first operation uses the value of the information unit,
later operations use the return value of the preceding operation
-
attribute value is "." => use the value of the information unit
-
attribute value is an NCName => use the return value of the preceding operation with
that operation ID (attribute "opID")
Note that the value of the information unit is always the data context for the method
"as a whole" (for
its first operation), but not necessarily for each of its operations. Every method
is therefore
bound to a particular information unit, as in object oriented programs every instance
method
is bound to a particular object.
The return value of a method is the return value of its last (or only) operation,
unless another operation has been marked with a special
attribute ("methodReturnValue") to yield the return value.
Execution context
When defining a method, the control data provide
The execution context specifies (a) when to execute the method and
(b) what to do with the return value (if any). Note the necessity of
specifying such an execution context, as the method will be invoked
after the XDML value is delivered to the XDML user.
We distinguish four types of execution context, which, taken together,
define the processing model of XDML. Future versions of XDML may add
further execution contexts. Each context may be viewed as the intent
with which the XDML provider defines the method. He may want to
Execution context "finalize"
Sometimes the XDML provider may want to supply intermediary data and
leave the finalization to postprocessing. There are three main reasons
for this pattern: (a) the finalization requires some processing resource
not available to the XDML provider, but available to an XDML operation;
(b) the finalization is deferred as it may turn out to be unnecessary;
(c) the finalization requires parameter values to be supplied by the
XDML user at invocation time.
For example, the data which an information unit should ultimately
supply may be obtained by submitting intermediary data to an XSLT
stylesheet. However, if the XDML provider is an XQuery program, it
cannot execute the XSLT processing. In this case, the XDML provider
may provide the intermediate data and bind the information unit to
the stylesheet execution. The execution context “finalize” ensures
that the finalization takes place as soon as the XDML user confirms
that finalizations are to be executed. The confirmation may be global
or restricted to a particular information unit. The code
XDMLProcessor xp = XDMLProcessorFactory.newXDMLProcessor();
XQSequence xdm = ...;
XDML xdml = xp.newXDML(xdm);
xdml.finalize();
loads an XDML value and triggers any finalizations, whereas
…
xdml.finalize(“conferenceProgram”);
triggers the finalization of information unit "conferenceProgram"
only. In general, finalization is achieved by executing a method
(one or more operations) defined for that purpose and replacing the value
of the unit by the return value of the method.
To give a second example, the intermediary submitted to finalization
may be the payload of a SOAP request. The finalization may then be
achieved by operation “sendSOAP”, which wraps the unit data in a
SOAP envelope, sends the request, receives the response and returns
its payload. Using this operation in the execution context “finalize”
will ensure that the information unit supplies the response payload,
rather than the request payload.
Execution context "execute"
To create data may be less than what the XDML provider wants to do:
his intent may be to execute actions related to the data. In some
cases, the data are only a means to an end which is such an action:
the data may represent, for example, a sequence of SQL statements, and the
action consist of their execution. In other cases, the data may be valuable as
such, but additional action is mandatory – for example, storage in
a file or in a database. In both situations, overall processing may
be simplified if the XDML provider may define the actions to be
executed, specifying all details, rather than rely on the XDML user
to know which actions to trigger and which details to specify.
The execution context “execute” takes care of this scenario. The
XDML user does not have to know which operations are executed.
He has to confirm, however, that any defined actions shall indeed
be executed. His responsibility is restricted to giving or refusing
“green light” to the actions defined by the XDML provider. The
confirmation may be global:
…
xdml.execute();
or restricted to a particular information unit:
…
xdml.execute(“cleanupScript”);
The XDML user does not receive a return value. Therefore, the
operations commanded by the XDM provider are always actions,
rather than evaluations: operations motivated by their side
effects, not by the production of a result value.
Execution context "enable"
A different intent of the XDML provider might be to make
certain evaluations or actions available, but leave it to the XDML
user if the processing is actually performed. An example
might be an evaluation which extracts some values from an
XML document, which might or might not be desired. The
execution context “enable” supports such intent: the evaluation
is only executed if the XDML user demands it explicitly,
identifying it by a name which the XDML provider has assigned
to it. In this example code:
String[] locations = (String[]) xdml.invoke(“waterReport”, “getLocations”);
the XDML user invokes an evaluation which is labeled "getLocations"
and bound to information unit "waterReport".
The name identifies a method (one or more operations) defined
for this unit and associated with the execution context "enable".
The method has
a signature, as implied by the use of $arg{argName}
references in the operation requests. The following
method definitions create two XDML methods, one without parameters
and the other with a string parameter "location". The methods
are implemented by one and two operations, respectively:
<xm:part name="waterReport" type="node">
<xm:interface>
<xm:method name="getLocations" returnType="strings">
<submitToXQuery>
<query>distinct-values(//location/@name)</query>
</submitToXQuery>
</xm:method>
<xm:method name="getResultTable" returnType="map_string_to_string">
<submitToXQuery>
<query>
declare variable $location external;
//location[@name eq $location]//substance/(@name, @quantity)
</query>
<xm:params location="$arg{location}"/>
</submitToXQuery>
<createMapFromStrings/>
</xm:method>
</xm:interface>
</xm:part>
These method definitions impart to the information unit
an interface of possible method invocations, which might be represented
in pseudo-code like so:
informationUnitInterface {
String[] getLocations();
Map<String,String> getResultTable(String location)
}
Execution context "translate"
The XDML provider might desire the XDML parser to deliver data
which are not a standard representation of XDM data. For example,
he might intend to deliver a map object, whereas the information
unit contains an XML fragment encoding the map entries. To achieve
this, the metadata specify the transformation of the unit data
into the desired representation. Conceptually, this may be viewed
as executing a method which produces the non-standard
representation and replaces the value of the unit with this
representation – which is essentially the same processing as provided
by a method in context “finalize”. We prefer, however, to
distinguish finalization in the sense described above from the
translation of the unit data into a specific data type. Such
translation we regard as processing associated with an
execution context "translate". Contrary
to the handling of finalization, the XDML user does not confirm
translation - translation is built into the XDML parser which
always delivers values in accordance to a defined translation. For example, this code:
Map<String,String> map = xdml.getPart("foo").getMapString2String()
retrieves the unit data as a map, rather than as an XML element
which is the XDM source format consumed by the XDML processor.
The XDML user can only retrieve the unit data as a map.
Method definitions
The processing of an information unit is organized as the execution of
methods. A method consists of one or several operations. The definition of a method
consists of the request message(s) launching its operation(s).
The definitions are associated with an execution context, where
execution contexts and method definitions are related as follows:
Table II
Execution contexts and method definitions.
Execution context |
Content |
finalize |
a single anonymous method (or empty)
|
execute |
a single anonymous method (or empty)
|
enable |
a set of named methods (possibly empty)
|
translate |
a single operation per target language (possibly none)
|
The encoding of method definitions reflects these relationships:
Table III
Execution contexts and their encoding.
Execution context |
Encoding |
finalize |
optional <xm:finalize> element, child elements are request messages
|
execute |
optional <xm:execute> element, child elements are request messages
|
enable |
optional <xm:interface> element, child elements are <xm:method>
elements representing named methods, whose child elements are request messages
|
translate |
zero or more <xm:translate> elements, each one representing a target language
and encoding the data type and translation parameters as attributes
|
The following listing presents a schematic example:
<xm:part name="foo" type="bar">
<xm:finalize>
<op1>...</op1>
<op2>...</op2>
</xm:finalize>
<xm:execute>
<op3>...</op3>
<op4>...</op4>
</xm:execute>
<xm:interface>
<xm:method name="m1" returnType="t1">
<op5>...</op5>
<op6>...</op6>
</xm:method>
<xm:method name="m2" returnType="t2">
<op7>...</op7>
<op8>...</op8>
</xm:method>
</xm:interface>
<xm:translate target="java" type="t3" att1="..." att2="..."/>
</xm:part>
And here comes a realistic example using three execution contexts, “finalize”, "execute"
and "enable".
It shows an information unit which is finalized into a Perl script to be executed
in context "execute"
and besides offering a little interface of methods to be invoked explicitly ("writeLog",
"save"):
<xm:part name="cleanupScript" type="node" finalType="string">
<xm:finalize>
<execAsXSLT serialize="true"/>
</xm:finalize>
<xm:execute>
<execAsPerl>
<xm:params options="-m cleanup"/>
</execAsPerl>
</xm:execute>
<xm:interface>
<xm:method name="writeLog">
<execAsPerl>
<xm:params options="-m writeLog -f $arg{fileName}"/>
</execAsPerl>
</xm:method>
<xm:method name="save">
<execAsPerl>
<xm:params options="-m save"/>
</execAsPerl>
</xm:method>
</xm:interface>
</xm:part>
XDML user perspective
An XDML value is a set of information units which may be
retrieved and – depending on the method definitions – processed
in a simplified way. An XDML value is represented by an object
whose interfaces provide for retrieval
(interface XMDLParser
) and processing
(XDMLProcessing
).
The following sections give a brief overview of these and further
interfaces which taken together amount to the user perspective
of XDML.
Obtaining and extending the XDML processor
The instantiation of XDML values requires an instance
of the XDML processor.
The processor object represents the engine responsible for
executing XDML operations. It implements interface
XDMLRegistry
which enables the XDML user
to register proprietary operations:
XDMLProcessor xp = XDMLProcessorFactory.newXDMLProcessor();
xp.registerXDMLOperations(new WaterOperations());
xp.registerXDMLOperations(new WeatherOperations());
Now we are ready to begin working with XDML values.
Obtaining an XDML value
An XDML value is represented by an instance of class
XDML
. The XDML processor offers a
generic method for instantiating XDML values:
void newXDML(Object dataSource) throws XDMLException;
Note that the signature does not constrain the data type of the data source.
Which type(s) are supported depends on the actual implementation of the
processor. Our prototypic implementation expects an
XQSequence
object, which is the XQJ representation
[
XQJ Spec] of an XDM value. Typical code snippet:
XQSequence xdm = …; // procure XDM value
XDML xdml = xp.newXDML(xdm); // create XDML value
Parsing an XDML value
Class XDML
implements a parser API which
supports iteration over the units as well as
random access:
interface XDMLParser {
InformationUnit next();
boolean hasNext();
void rewind();
InformationUnit getPart(QName partName);
InformationUnit getPart(QName[] partNames); // access nested part
InformationUnit getPartByID(String partID);
…
}
If the information unit is complex, it is represented by an
XDML
object delivered by the
InformationUnit
object:
class InformationUnit implements DataUnit, MetadataUnit {
XDML getComplexValue();
boolean isValueComplex();
...
Class
InformationUnit
implements two interfaces for accessing
the data value (interface
DataUnit
) and metadata
(
MetadataUnit
) of a simple unit.
The
data value is always retrieved
as a single object (which may
be an array object) – never by iterating over the items of the
value. There are many possible types and for each
one there is a specific retrieval method. The range of data types
includes several types which have no default mapping to an XDM
value, as the interface must also handle values which result
from a value translation (via
<xm:translate>
metadata)
or which are the return value of an XDML operation -
e.g. several map types:
interface DataUnit {
// *** read value
Node getNode();
Node[] getNodes();
int getInteger();
int[] getIntegers();
String getString();
String[] getStrings();
Duration getDuration();
Duration[] getDurations();
…
Object getObject(); // allows for a DataUnit to contain ANY type
// *** write value
void setNode(Node value);
void setNodes(Node[] value);
...
void setObject(Object value, String typeName);
}
The retrieval of
metadata is different
dependent on the metadata component. Descriptive metadata and translation
metadata are delivered as a metadata set:
interface MetadataUnit {
MetadataSet getDescriptiveMetadata(String topic);
MetadataSet getTranslationMetadata(String targetLanguage);
String[] getDescriptiveTopics();
String[] getTranslationTargetLanguages();
...
}
A metadata set is a set of named properties; similar to the
parameters of request messages, property names are QNames
and values are either a string, or a node, or a sequence of nodes:
interface MetadataSet {
QName[] getPropertyNames();
String getStringProperty(QName name);
Node getNodeProperty(QName name);
Node[] getNodesProperty(QName name);
…
}
Other metadata – that is, metadata components corresponding to
execution contexts (other than “translate”) – are delivered as
methods or a map of named methods:
interface MetadataUnit {
…
Method getFinalizationMethod();
Method getExecutionMethod();
Map<QName, Method> getInterfaceMethods();
}
A
Method
is a sequence of operation requests:
interface Method {
int getOperationCount();
OperationRequest getOperationRequest(int index);
Integer getDataContext(int index);
// data context is the return value of a preceding operation (>0), or the unit value (0), or null
}
See
section “Data model of input and output” for details
about interface OperationRequest.
Processing an XDML value
Any processing happens in response to an API call of the XDML user (finalize
, execute
,
invoke
). Here comes the processing interface implemented by class XDML
:
interface XDMLProcessing {
void finalize();
void finalize(Arguments args);
void finalize(QName part);
void finalize(QName part, Arguments args);
void execute();
void execute(Arguments args);
void execute(QName part);
void execute(QName part, Arguments args);
Object invoke(QName part, QName methodName);
Object invoke(QName part, QName methodName, Arguments args);
boolean isFinalized();
boolean isFinalized(QName part);
boolean isExecuted();
boolean isExecuted(QName part);
}
If arguments are passed to the processing, they will be used in the respective request
messages
for resolving argument references of the syntax
$arg(argName)
(see
section “Parameter values supplied by the XDML user”). Setting arguments is straightforward:
Document weatherData = ...;
String location = "NY";
Arguments args = xdml.newArguments();
args.set(new QName("location"), location);
args.set(new QName("weatherData"), weatherData);
Example
An example handles the following scenario. Two datasets – one representing
hydrological measurements, the other meteorological data – are the input
for an evaluation yielding an XML report. Some value extraction, as
well as HTML and CVS representations of
the report should be available on demand. Before creating the report, the
input datasets must be procured: weather data are obtained from a SOAP
service, water data are downloaded from a relational database. The
following code snippet demonstrates XDML user code:
// *** obtain XDML value
XDMLProcessor xp = XDMLProcessorFactory.newXDMLProcessor();
XQSequence xdm = …; // procure source data (e.g. exec XQuery)
XDML xdml = xp.newXDML(xdm);
// *** use XDML value
xdml.finalize();
Map<String,String> results = (Map<String,String>) xdml.invoke("report", "getResultTable");
String html = (String) xdml.invoke("report", "getHTML");
String[] cvs = (String[]) xdml.invoke("report", "getCVS");
Although the processing requires the use of various technologies
(XQuery, XSLT, SOAP, SQL), the client code is very simple and
unawares of the complexity involved:
-
Calling finalize
accomplishes ...
-
retrieval of a dataset via SOAP
-
retrieval of a dataset via SQL
-
execution of an XQuery script producing the XML report
-
Calling invoke(..., "getResultTable")
creates a value extraction
-
Calling invoke(..., "getHtml")
creates an HTML representation
-
Calling invoke(..., "getCVS")
creates a CVS representation
The following table summarizes the structure of the XDML value enabling
this simplicity:
Table IV
Example: information units providing simplified processing.
Unit name |
Semantics |
(Initial) unit value |
Context : used operations |
toHTML |
tool for transforming the report to HTML |
an XSLT stylesheet |
- |
toCVS |
tool for transforming the report to CVS |
an XQuery program |
- |
weatherData |
weather data |
payload of a SOAP request |
finalize:sendSOAP |
waterData |
water data |
text of a SQL SELECT statement |
finalize:execAsSQL |
report |
an XML report with an interface
|
an XQuery program |
finalize:execAsXQuery
invoke:createMapFromStrings
invoke:submitToXQuery
invoke:submitToXSLT
|
An abbreviated representation of the XDM value follows:
<xm:part name="toHTML" partID="toHTML" type="node" private="true"/>,
<xsl:transform…>…</xsl:transform>
,
<xm:part name="toCVS" partID="toCVS" type="string" private="true">,
xquery 1.0 …
…
,
<xm:part name="weatherData" partID="we" type="node" finalType="node">
<xm:finalize>
<sendSOAP href="…" />
</xm:finalize>
</xm:part>,
<getWeatherData>…</getWeatherData>
,
<xm:part name="waterData" partID="wa" type="string" finalType="node">
<xm:finalize>
<execAsSQL driver="…" host="…" db="…" user="…" password="…" format="xml"/>
</xm:finalize>
</xm:part>,
SELECT …
,
<xm:part name="report" type="string" finalType="node">
<xm:finalize requiredParts="we wa">
<execAsXQuery resultType="node">
<xm:params>
<weatherData>$part{we}</weatherData>
<waterData>$part{wa}</waterData>
</xm:params>
</execAsXQuery>
</xm:finalize>
<xm:interface>
<xm:method name="getResultTable" returnType="map_string_to_string">
<submitToXQuery resultType="strings">
<query>...</query>
</submitToXQuery>
<createMapFromStrings/>
</xm:method>
<xm:method name="toHTML" returnType="string">
<submitToXSLT serialize="true">
<stylesheet>$part{toHTML}</stylesheet>
</submitToXSLT>
</xm:method>
<xm:method name="toCVS" returnType="strings">
<submitToXQuery resultType="strings">
<query>$part{toCVS}</query>
</submitToXQuery>
</xm:method>
</xm:interface>
</xm:part>,
xquery 1.0
declare variable $weatherData as node() external;
declare variable $waterData as node() external;
<waterReport>{
…
}</waterReport>
Discussion
The languages XQuery and XSLT enable a very efficient and elegant processing
of XML resources. Their integration into programs written in general purpose
languages - like Java - is therefore highly desirable. The potential
contribution is
however limited by three major issues. First, XQuery and XSLT are designed
to create information, rather than execute actions with side effects.
Second, these languages are rather closed systems,
without a concept of embedding other technologies and domain-specific
functionality. Third,
the information delivered (XML and/or atomic values) is pure information without
behaviour, rather than objects associating information with
specific behaviour, which means that downstream usage of the information
may be a relatively complex and challenging task. These limitations of effect -
"no actions, closed functionality, no behaviour" - is at odds with the
enormous power of the means which the X-languages offer.
XProc [W3C XPROC] addresses the first two limitations: it integrates
the major XML technologies (XSLT, XQuery, XML Schema, ...) into a single
script language, provides openness
to other technologies (HTTP, system commands, ...) and enables to
combine side-effect free processing with actions in a well-controlled
way (based on distinct steps). XProc is a powerful approach
to accomplish complex XML processing.
XDML has a different emphasis: it concentrates on integrating
XML technology into general purpose languages.
XDML strives to broaden the
scope of what the X-developer can achieve as a
contributor to a non-XML environment - rather than as the author
of a standalone processing. He is enabled to
define a complex postprocessing and its control by API client actions.
This creates a novel
possibility of leveraging XML technology to generate
information associated with behaviour:
information with an interface.
The usefulness of the behaviour hinges critically upon the functional
wealth offered by the available XDML operations. Therefore we believe
that the easy extensibility of the XDML processor by proprietary,
domain specific XDML operations may be of key importance for
the value which XDML has to offer.