[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