We have some XML documents that use dashes (-) in XML elements which does not play nice with objectified xml elements.
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.3R7/junos"> <route-information xmlns="http://xml.juniper.net/junos/12.3R7/junos-routing"> <route-table> <table-name>inet.0</table-name> <destination-count>12</destination-count> <total-route-count>19</total-route-count> <active-route-count>12</active-route-count> <holddown-route-count>0</holddown-route-count> <hidden-route-count>0</hidden-route-count> </route-table> </route-information> <cli> <banner>{master}</banner> </cli>
So, the obvious happens, and i can access it fine via getattr()
In [144]: ri = root.getchildren()[0] In [145]: ri.route-table --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-145-e452e1935e9d> in <module>() ----> 1 ri.route-table /opt/brazil-pkg-cache/packages/Lxml/Lxml-3.4.x.13.220/RHEL5_64/DEV.STD.PTHREAD/build/lib/python2.7/site-packages/lxml/objectify.so in lxml.objectify.ObjectifiedElement.__getattr__ (src/lxml/lxml.objectify.c:3494)() /opt/brazil-pkg-cache/packages/Lxml/Lxml-3.4.x.13.220/RHEL5_64/DEV.STD.PTHREAD/build/lib/python2.7/site-packages/lxml/objectify.so in lxml.objectify._lookupChildOrRaise (src/lxml/lxml.objectify.c:5956)() AttributeError: no such child: {http://xml.juniper.net/junos/12.3R7/junos-routing}route In [146]: getattr(ri, 'route-table') Out[146]: <Element {http://xml.juniper.net/junos/12.3R7/junos-routing}route-table at 0x7f5f9cd5bb48>
So, I figure this is a nice case to subclass and define my own getattribute that does some converting _ to - on behalf of the user so they can access attributes like ri.route_table.
I also want this to be deal with arbitrary depth and turn this:
getattr(getattr(ri, 'route-table'), 'total-route-count')
Into this:
ri.route_table.total_route_count
So I need to find a way or sublclassing lxml.objectify.ObjectifiedElement but also make it the value to used to create the objects in the first place
My class would be something basic like (rough idea):
class ObjectifiedRouteInformation(lxml.objectify.ObjectifiedElement): """ An adapter class for extracting values from Junos XML RPC replies easier to use and undertand """ def __getattribute__(self, attr): attr = attr.replace('_', '-') lxml.objectify.ObjectifiedElement.__getattribute__(self, attr)
Documentation that helped me get to where I am: http://lxml.de/1.3/objectify.html#setting-up-lxml-objectify
Shows how to alter the parser to create objectified elements:
DEFAULT_PARSER = etree.XMLParser(remove_blank_text=True) DEFAULT_PARSER.setElementClassLookup(objectify.ObjectifyElementClassLookup())
Is there any way to inject my new class to make it the default objectified class used to instantiate children.
As all of this is hidden behind c libraries, it's hard to make this determination.
Thanks in advance.
No comments:
Post a Comment