[PEAK] XML Configuration and Serialization
Phillip J. Eby
pje at telecommunity.com
Mon May 31 22:23:08 EDT 2004
While mulling over my ideas for simplifying peak.web, I was thinking about
how to define a "site map" configuration for an application (or portion
thereof) that would specify how to wrap domain objects in views, what the
URL trees look like and so forth. I was originally thinking that this
would use ZConfig as a nice "quick and dirty" format. But, as I thought
about it further, I realized that ZConfig is just too limiting in its
syntax and the ways it can be mapped to objects, to accomplish what I had
in mind.
So, what I'll probably do instead is use XML. And, instead of it being a
special XML format just for peak.web, I figure I'll create a generic "XML
to objects" mapping: a kind of 'XConfig' counterpart to 'ZConfig', you
might say.
Unlike ZConfig, however, we won't use a separate schema. Instead, we'll
use PEAK's existing configuration system. I figure it'll look something
like this:
[XML Elements for http://peak.telecommunity.com/example_namespace]
foo = "somepackage.someclass"
bar = "somepackage.anotherclass"
* = "somepackage.function_that_raises_an_error"
So, this simple schema allows 'foo' and 'bar' elements at its top
level. As with DOMlets, configuration lookup takes place relative to the
containing XML element, so this means that 'foo' and 'bar' could define
their own "XML Elements for <namespace>" that defined other elements
available inside a foo or bar element.
There are some really interesting possibilities for component assembly
here. Because XML namespaces are infinitely flexible, you can create
general-purpose useful tags, like:
[XML Elements for http://peak.telecommunity.com/example_namespace]
include = "somepackage.classThatHandlesIncludes"
If I do this right, it should be possible to create an all-purpose
"include" tag that can be used to process another file/URL/whatever as
though it were part of the containing document.
This technology could also be directly applied to managing XML Streams,
such as are used by Jabber. Effectively, XML streams can be directly
unserialized to live objects that do as the other end of the connection
requests. Of course, for that to be *safe*, it'd be necessary to declare
something like:
[XML Elements for *]
* = "somepackage:safe_unsupported_element"
[XML Attributes for *]
* = "somepackage:safe_unsupported_attribute"
in the configuration of the component that's doing the processing, so that
anything that isn't explicitly registered as safe, is not invocable by the
other end of the connection.
So far, the whole idea is like a cross between DOMlets in
peak.web.template, and the peak.util.SOX module. I'm thinking that with a
bit more work, I could refactor DOMlets to be based on this new
idea. Specifically, if one can also define *attributes* by namespace...
[XML Attributes for http://peak.telecommunity.com/DOMlets/]
define = "peak.web.templates:function_to_do_defines"
domlet = "peak.web.templates:function_to_DOMletize"
The idea here is that any attributes of a tag that are associated with a
non-default namespace, will get looked up, and invoked to wrap the element
being generated.
To implement this, we'll need:
* A 'config.XMLNamespace()' key type, that matches first by string
comparison, and then matches '*' (so that we can have a wildcard namespace)
* .ini section handlers for the 'XML Attributes for' and 'XML Elements for'
directives, that register multi-keys of (interface,namespace,property)
where interface is the attribute or element interface, namespace is the
section namespace, and property is the tag name being defined.
* A refactored version of the current DOMlet parser that works against a
more generic set of interfaces, and doesn't have any built-in knowledge of
the domlet or define attributes. The expanded interfaces would need an
analog to SOX's 'finish()' method. It would basically be the same as
IDOMletElement, minus the 'addParameter()' method, but with a
'finishedNode()' method added.
* Revised versions of the IDOMlet*Factory interfaces to trim back on some
of the DOMlet-specific handling support. (e.g. domletProperty, dataSpec,
nonEmpty, and paramName would need to be parsed by the factory, rather than
supplied by the parser, and there'd need to be namespace info added to the
signature).
* A default adapter from binding.IComponent to whatever the IDOMletElement
interface gets replaced with, that implements factory lookups.
* An 'xml' reference type, so that URLs like "ref:xml at file:///blah" will be
usable to deserialize semi-arbitrary XML.
These changes may have some impact on custom DOMlets, although I'll try to
keep it to a minimum by ensuring that created DOMlets end up with the same
attributes as before, even though different classes will be doing the work
of setting them up.
More information about the PEAK
mailing list