Continuing on with the xml_schema thoughts, I've been mucking around
with subclassing Element to provide schema information, mapping python
attribute names to child elements and node attributes.
I envision subclassing Element and providing schema information as class
instance names:
class Spam(Element):
sliceThickness = Attribute
class Eggs(Element):
disposition = Attribute
class Breakfast(Element):
spam = Spam
eggs = Eggs
Now when I create some breakfast:
breakfast = Breakfast()
assert breakfast.xml_schema.isElement('spam')
I can give myself a nice slice:
breakfast.spam.sliceThickness = "25mm"
Or maybe even another, thinner piece:
breakfast.append(Spam(sliceThickness="20mm"))
breakfast.append("Spam? I love it!")
The usual bindery stuff should behave:
assert len(breakfast.spam) == 2
And now some eggs:
eggs = Eggs("Yum", disposition="over-easy")
breakfast.append(eggs)
I would like to add a rectangle:
class Rectangle(Element):
xml_name = 'rect'
xml_namespace = u'http://w3.org/2000/svg'
x = Attribute
y = Attribute
width = Attribute
height = Attribute
breakfast.append(Rectangle())
OK, now I'm hungry.
Joel
For dealing with files that have a published schema, it would be cool to
have a parser that knows how to build the appropriate classes from an
XSD document.
I wrote:
> class Eggs(Element):
> disposition = Attribute
...and...
> eggs = Eggs("Yum", disposition="over-easy")
> breakfast.append(eggs)
I don't know how well this design pattern is used, but treating kwargs
in the ctor as XML attributes has worked really well for me, for example:
div = DIV(class_="queryResults")
div.append( H1("Query Results") )
div.append( TABLE( TR( TD("a"), TD("b") )))
Knowing how to consistently wrap Python keywords is important:
x = Element()
x.xml_content_model.asAttribute( 'class', 'class_' )
Metaclassing Attribute for content validation when documents are being
built/modified is nice too:
class RegexAttribute:
def __init__(self, expr):
self.exprRE = re.compile(expr)
def __call__(self, value):
if value and not self.exprRE.match(value):
raise ValueError, "invalid"
return Attribute(value)
class Spam(Element):
sliceThickness = RegexAttribute("[0-9]+(mm|in)")
Joel