Subclassing Element

0 views
Skip to first unread message

Joel Bender

unread,
Mar 25, 2008, 1:20:12 PM3/25/08
to amara...@googlegroups.com
Hi there, me again.

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

Joel Bender

unread,
Mar 26, 2008, 9:08:50 AM3/26/08
to amara...@googlegroups.com
The spam continues...

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

Uche Ogbuji

unread,
Mar 26, 2008, 11:12:53 PM3/26/08
to Amara
Top-posting, sorry. Overall not much to respond, except that this is
exactly the sort of usage we plan to make easier in 2.x.

--Uche

Uche Ogbuji

unread,
Mar 26, 2008, 11:18:27 PM3/26/08
to Amara
On Mar 26, 7:08 am, Joel Bender <j...@cornell.edu> wrote:
> The spam continues...
>
> 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.

This is in the plan, though I plan to prioritize RNG over WXS :-)

> 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") )))

Yep. This sort of thing is also in the plan.

> Knowing how to consistently wrap Python keywords is important:
>
> x = Element()
> x.xml_content_model.asAttribute( 'class', 'class_' )

I think how to dismbiguate from Python keywords is just another facet
of what should be defined in a parse rule.

> 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)

Nice use case for clearer subclassing. I'll keep it in mind.

> class Spam(Element):
> sliceThickness = RegexAttribute("[0-9]+(mm|in)")

--Uche
Reply all
Reply to author
Forward
0 new messages