Re: [xml-bindings]Python bindings suggestions



On Mon, Mar 04, 2002 at 10:05:03PM +0000, Gary Benson wrote:
> 
> 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")

  well I would have to define an treeError class and raise this, in this
case. I agree this would simplify programming with the bindings a lot,
  => TODO

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

Yep for the most part, basically I would raise this for all methods returning
xmlCore (or subclasses of it). Should that be systematic, i.e. any function
or method expecting to return a class should raise exception if the return
is None ?

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

  Actually the wrappers checks for the existence of the class attribute
so all defaults appears like 
    def foo(self...):
        pass
  Except they are processed quite faster since the call to Python is not made.
But I agree a full exemple should be provided at least.

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

  Hum, I would need a wrapper for something like
    xmlDocPtr       xmlSAXParseFile         (xmlSAXHandlerPtr sax,
                                             const char *filename,
					     int recovery);

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

   agreed,

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

   "/photodb/film[ num=%s]" % film
   would give 
   "/photodb/film[ num=022]"
   and that may not work well, possibly
   "/photodb/film[ num='%s']" % film
   would give better results

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

  The context should really be created against the document, but 
an accessor should be added to allow setting the current node, this is
lacking ATM, it's just an entry needed in libxml2-python-api.xml to 
provided it.

  There is definitely a bit of polishing needed, thanks for the suggestions
I will try to implement them before the next release.

Daniel

-- 
Daniel Veillard      | Red Hat Network https://rhn.redhat.com/
veillard redhat com  | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/



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