[lxml-dev] objectify factories

Stefan Behnel stefan_ml at behnel.de
Wed Aug 22 20:29:56 CEST 2007


Stefan Behnel wrote:
> Regarding the TypedElementMaker, I think that if we write one that is adapted
> to objectify, we should not stop half-way. We should remove the "typemap"
> thing and just use the type inference mechanisms that objectify already
> provides. You can take a look into that, if you want, otherwise I will try to
> come up with an implementation when I find the time (which may be after the
> release of 2.0alpha1).

... or a bit before :)

This code is what I think might work well for objectify. Any general comments
before I go any further?

Stefan


cdef class ElementMaker:
    cdef object _makeelement
    cdef object _namespace
    cdef object _nsmap
    def __init__(self, namespace=None, nsmap=None, makeelement=None):
        self._nsmap = nsmap
        if namespace is None:
            self._namespace = None
        else:
            self._namespace = "{%s}" % namespace
        if makeelement is not None:
            assert callable(makeelement)
            self._makeelement = makeelement
        else:
            self._makeelement = None

    def __getattr__(self, tag):
        if tag[0] != "{" and self._namespace is not None:
            tag = self._namespace + tag
        return _ObjectifyElementMakerCaller(
            self._makeelement, tag, self._nsmap)

cdef class _ObjectifyElementMakerCaller:
    cdef object _tag
    cdef object _nsmap
    cdef object _element_factory
    def __init__(self, element_factory, tag, nsmap):
        self._element_factory = element_factory
        self._tag = tag
        self._nsmap = nsmap

    def __call__(self, *children, **attrib):
        cdef _ObjectifyElementMakerCaller elementMaker
        cdef python.PyObject* pytype
        cdef _Element element
        if self._element_factory is None:
            element = cetree.makeElement(
                self._tag, None, objectify_parser,
                None, None, attrib, self._nsmap)
        else:
            element = self._element_factory(self._tag, attrib, self._nsmap)

        for child in children:
            if child is None:
                if len(children) == 1:
                    cetree.setAttributeValue(
                        element, XML_SCHEMA_INSTANCE_NIL_ATTR, "true")
            elif python._isString(child):
                _add_text(element, child)
            elif isinstance(child, _Element):
                cetree.appendChild(element, child)
            elif isinstance(child, _ObjectifyElementMakerCaller):
                elementMaker = <_ObjectifyElementMakerCaller>child
                if elementMaker._element_factory is None:
                    child = cetree.makeElement(
                        elementMaker._tag, element._doc, objectify_parser,
                        None, None, None, None)
                else:
                    child = elementMaker._element_factory(
                        (<_ObjectifyElementMakerCaller>child)._tag)
                cetree.appendChild(element, child)
            else:
                pytype = python.PyDict_GetItem(
                    _PYTYPE_DICT, _typename(child))
                if pytype is not NULL:
                    (<PyType>pytype)._stringify(element, child)
                else:
                    child = str(child)
                    _add_text(element, child)

        return element




More information about the lxml-dev mailing list