> > Which xmlns:ns1 gets "redefined" because I just didn't figure out how > > get xmlns:ns0 definition into the Workbook tag. But too bad for me. > > What about actually *reading* the links I post? > > http://codespeak.net/lxml/tutorial.html#the-e-factory > > Hint: look out for the "nsmap" keyword argument.
That solved the problem. nsmap doesn't set the root xmlns, but el.set does. So that cleared up the [hugevariable] gripe. Revision separates code from data. def Cell( p, index= None, styleid= None ): el= etree.SubElement( p, 'Cell' ) if index is not None: el.set( SS+ 'Index', index ) if styleid is not None: el.set( SS+ 'StyleID', styleid ) return el becomes class Cell( XMLable ): ctor= XMLable.CTor( ( 'index', SS+ 'Index' ), ( 'style', SS+ 'StyleID' ) ) ftor= XMLable.FTor( { 'style': lambda x: x.styleid } ) 29 lines, loosely packed, define base class; 29 define the subclasses Workbook, Worksheet, &c., also loose. class Data( XMLable ): ctor= XMLable.CTor( ( 'type', SS+ 'Type' ), ( 'data', XMLable.Text ) ) XMLable.Text pseudo-flag indicates to call node.data= X where node.set( tag, X ) is called. Tag present in XMLable.ftor indicates to call node.set( tag, ftor[tag]( X ) ). class Font( XMLable ): #jtor= JTor( 'family', X+ 'Family', req='Swiss' ), JTor( 'bold', SS+ 'Bold', lambda x: str( int( x ) ) ) ctor= XMLable.CTor( ( 'family', X+ 'Family' ), ( 'bold', SS+ 'Bold' ) ) ftor= XMLable.FTor( { 'bold': lambda x: str( int( x ) ) } ) JTor combines CTor and FTor allowing for extension, separating data into data structure, but is developing. One could even put that spec in XML! Yes: in the example, the base class + derivatives comprise more code, 29 + 29 = 58 lines over the earlier 46. Actual construction underwent a slight adjustment, still 9 lines. Hearing arguments on payoff and extensibility. Full implementation present; remove in replies. Aside, in the C++ equivalent, each XMLable derivative has a class- static list of JTor derivatives, "static JTor* specs[];", the population of which is declared and initialized globally, and a "virtual JTor* GetSpec( int i ) { return specs[ i ]; }" implementation. CMIIW, correct me if I'm wrong; +1 on Python. The for-statements in XMLable.__init__ could conflate; parameter extraction, which parameters may be specified by place or keyword, is unclear. Is "if ca[1] is XMLable.Text:" a special case, and if so, is it handled correctly? Ought JTor to contain a visit method to the end, which calls node.set in the base class? It leads to redundancy, but code is code. Thence comes the moral, 'No functions in constructors', and "if ca[1] is XMLable.Text:" is not a callback. Aside, what is? from lxml import etree class XMLable: cname= '' Text= object() class CTor: def __init__( self, *ar ): self.ar, self.kwar= ar, dict( ar ) ctor= CTor() FTor= dict ftor= {} def __init__( self, par= None, *ar, **kwar ): nsmap= kwar.pop( 'nsmap', None ) if par is None: self.node= etree.Element( self.cname or self.__class__.__name__, nsmap= nsmap ) else: self.node= etree.SubElement( par.node, self.cname or self.__class__.__name__, nsmap= nsmap ) for a, ca in zip( ar, self.ctor.ar ): if ca[0] in self.ftor: a= self.ftor[ ca[0] ]( a ) if ca[1] is XMLable.Text: self.node.text= a else: self.node.set( ca[1], a ) for k, v in kwar.items(): if k in self.ftor: v= self.ftor[ k ]( v ) if self.ctor.kwar[ k ] is XMLable.Text: self.node.text= v else: self.node.set( self.ctor.kwar[ k ], str( v ) ) SS= '{urn:schemas-microsoft-com:office:spreadsheet}' X= '{urn:schemas-microsoft-com:office:excel}' class Workbook( XMLable ): #jtor= JTor( 'xmlns', req= 'urn:schemas-microsoft- com:office:spreadsheet' ) def __init__( self ): nns= { 'x': 'urn:schemas-microsoft-com:office:excel', 'ss': 'urn:schemas-microsoft-com:office:spreadsheet' } XMLable.__init__( self, nsmap= nns ) self.node.set( 'xmlns', 'urn:schemas-microsoft- com:office:spreadsheet' ) self.styles= Styles( self ) class Worksheet( XMLable ): ctor= XMLable.CTor( ( 'name', SS+ 'Name' ) ) class Table( XMLable ): pass class Row( XMLable ): ctor= XMLable.CTor( ( 'index', SS+ 'Index' ) ) class Cell( XMLable ): ctor= XMLable.CTor( ( 'index', SS+ 'Index' ), ( 'style', SS+ 'StyleID' ) ) ftor= XMLable.FTor( { 'style': lambda x: x.styleid } ) class Data( XMLable ): ctor= XMLable.CTor( ( 'type', SS+ 'Type' ), ( 'data', XMLable.Text ) ) class Styles( XMLable ): pass class Font( XMLable ): #jtor= JTor( 'family', X+ 'Family', req='Swiss' ), Jtor( 'bold', SS+ 'Bold', lambda x: str( int( x ) ) ) ctor= XMLable.CTor( ( 'family', X+ 'Family' ), ( 'bold', SS+ 'Bold' ) ) ftor= XMLable.FTor( { 'bold': lambda x: str( int( x ) ) } ) class Style( XMLable ): styles= {} ctor= XMLable.CTor( ( 'styleid', SS+ 'ID' ) ) def __init__( self, par= None, *ar, **kwar ): self.styleid= 's%i'% ( 21+ len( Style.styles ) ) Style.styles[ self.styleid ]= self XMLable.__init__( self, par.styles, self.styleid ) Font( self, *ar, **kwar ) book= Workbook() sheet= Worksheet( book, 'WSheet1' ) table= Table( sheet ) row= Row( table, index= '2' ) style= Style( book, 'Swiss', True ) celli= Cell( row, style= style ) datai= Data( celli, 'Number', '123' ) cellj= Cell( row, index= 3 ) dataj= Data( cellj, 'String', 'abc' ) out= etree.tostring( book.node, pretty_print= True, xml_declaration=True ) print( out ) open( 'xl.xml', 'w' ).write( out ) new= etree.XML( out ) etree.XML( etree.tostring( book.node ) ) out= etree.tostring( new, pretty_print= True, xml_declaration=True ) print( out ) -- http://mail.python.org/mailman/listinfo/python-list