XML pickle

C

castironpi

Which xmlns:ns1 gets "redefined" because I just didn't figure out how
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:eek:ffice:spreadsheet}'
X= '{urn:schemas-microsoft-com:eek:ffice:excel}'

class Workbook( XMLable ):
#jtor= JTor( 'xmlns', req= 'urn:schemas-microsoft-
com:eek:ffice:spreadsheet' )
def __init__( self ):
nns= { 'x': 'urn:schemas-microsoft-com:eek:ffice:excel',
'ss': 'urn:schemas-microsoft-com:eek:ffice:spreadsheet' }
XMLable.__init__( self, nsmap= nns )
self.node.set( 'xmlns', 'urn:schemas-microsoft-
com:eek:ffice: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 )
 
C

castironpi

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:eek:ffice:spreadsheet}'
X= '{urn:schemas-microsoft-com:eek:ffice:excel}'

class Workbook( XMLable ):
        #jtor= JTor( 'xmlns', req= 'urn:schemas-microsoft-
com:eek:ffice:spreadsheet' )
        def __init__( self ):
                nns= { 'x': 'urn:schemas-microsoft-com:eek:ffice:excel',
                        'ss': 'urn:schemas-microsoft-com:eek:ffice:spreadsheet' }
                XMLable.__init__( self, nsmap= nns )
                self.node.set( 'xmlns', 'urn:schemas-microsoft-
com:eek:ffice: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 )

This is one way of eliminating a particular redundancy that showed up
in the first implementation. I've already excluded some potential
uses of XMLable. I've, in other words, made assumptions.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top