[xml-bindings]Python bindings suggestions



Hi all,

Okay, over the past few days I've been using the Python bindings a lot,
and have tripped a few things (probably because I've done very little
libxml programming in C so I don't have any preconceived notions of how
the library works). So I have a couple of suggestions (which can hopefully 
be dealt with in the automatic code generator) and a couple of questions:

One thing I'd like to get rid of is all the 'if ret == None: return None's 
that signify that something failed in libxml2.py. The Python way of doing 
this is very much "if something fails, throw an exception". I tend to use 
something like this for my stuff:

    class error(exceptions.Exception):
        def __init__(self, msg):
            self.msg = msg
        def __str__(self):
            return self.msg

This would probably be more easily done in the Python part:

    ret = _libxml.xmlNewTextChild(self._o, ns__o, name, content)
    if ret == None: raise error("xmlNewTextChild() failed")

That way you get something like "libxml2.error: xmlNewTextChild() failed" 
in the backtrace, and you can "except libxml2.error" to catch problems if 
you want. Hopefully this won't be too hard to implement since I understand 
that libxml2.py is automatically generated anyway.

My second suggestion is this: in quite a lot of Python modules where is
something that requires a callback there will be an example one filled
with empty functions. For the SAX parser, for example, something like 
(only a couple of methods shown):

    class SAXCallback:
        """Base class for SAX handlers"""

        def startElement(self, tag, attrs):
            """Called at the start of every element.

            TAG is the name of the element
            ATTRS is a dictionary of the element's attributes
            """
            pass

        def endElement(self, tag):
            """Called at the end of every element

            TAG is the name of the element
            """
            pass

        # ... other methods ...

        def warning(self, msg):
            raise error(msg)

        def error(self, msg):
            raise error(msg)

        def fatalError(self, msg):
            raise error(msg)

That way, all the error handling stuff is there already (unless they 
override it with something less severe) and they have a template that 
basically documents itself.

Finally, I had a couple of questions:

1. The only SAX parser creator seems to be a memory parser -- is there a 
   way of creating one that will parse a file instead? I'm currently 
   using something like:

    def parseFile(path, handler):
        ctxt = None
        file = open(path, "r")
        while 1:
            chunk = file.read(1024)
            if len(chunk) == 0:
                break
            if not ctxt:
                ctxt = libxml2.createPushParser(handler, chunk, len(chunk), path)
            else:
                ctxt.parseChunk(chunk, len(chunk), len(chunk)!=1024)

   It's not a problem, but it seems like something I should be able to do 
   with the library.

2. I tried using the following bit of XPath but it didn't return any nodes 
   (it should have returned one). Have I done something stupid, or is it 
   a bug?

    film = "022"
    doc = libxml2.parseFile(path)
    ctxt = doc.xpathNewContext()
    nodes = ctxt.xpathEval("/photodb/film[ num=%s]" % film)

3. How do you evaluate an XPath expression with a relative path? For 
   instance, if the above example had worked and nodes[0] was an xmlNode, 
   how would I select into it? I'd _expect_ to do something like:

    film_node = nodes[0]
    photo = "12"
    ctxt2 = film_node.xpathNewContext()
    nodes2 = ctxt2.xpathEval(photo[ num=%s]" % photo)

   But of course that doesn't work ;-)

Thanks in advance,
Gary

[ gary inauspicious org ][ GnuPG 85A8F78B ][ http://inauspicious.org/ ]




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]