<s> from types import StringTypes <EOL> from lxml import etree <EOL> from StringIO import StringIO <EOL> from foam . sfa . util . faults import InvalidXML <EOL> from foam . sfa . rspecs . elements . element import Element <EOL> class XpathFilter : <EOL> @ staticmethod <EOL> def filter_value ( key , value ) : <EOL> xpath = "<STR_LIT>" <EOL> if isinstance ( value , str ) : <EOL> if '<STR_LIT:*>' in value : <EOL> value = value . replace ( '<STR_LIT:*>' , '<STR_LIT>' ) <EOL> xpath = '<STR_LIT>' % ( key , value ) <EOL> else : <EOL> xpath = '<STR_LIT>' % ( key , value ) <EOL> return xpath <EOL> @ staticmethod <EOL> def xpath ( filter = { } ) : <EOL> xpath = "<STR_LIT>" <EOL> if filter : <EOL> filter_list = [ ] <EOL> for ( key , value ) in filter . items ( ) : <EOL> if key == '<STR_LIT:text>' : <EOL> key = '<STR_LIT>' <EOL> else : <EOL> key = '<STR_LIT:@>' + key <EOL> if isinstance ( value , str ) : <EOL> filter_list . append ( XpathFilter . filter_value ( key , value ) ) <EOL> elif isinstance ( value , list ) : <EOL> stmt = '<STR_LIT>' . join ( [ XpathFilter . filter_value ( key , str ( val ) ) for val in value ] ) <EOL> filter_list . append ( stmt ) <EOL> if filter_list : <EOL> xpath = '<STR_LIT>' . join ( filter_list ) <EOL> xpath = '<STR_LIT:[>' + xpath + '<STR_LIT:]>' <EOL> return xpath <EOL> class XmlElement : <EOL> def __init__ ( self , element , namespaces ) : <EOL> self . element = element <EOL> self . namespaces = namespaces <EOL> def xpath ( self , xpath , namespaces = None ) : <EOL> if not namespaces : <EOL> namespaces = self . namespaces <EOL> elems = self . element . xpath ( xpath , namespaces = namespaces ) <EOL> return [ XmlElement ( elem , namespaces ) for elem in elems ] <EOL> def add_element ( self , tagname , ** kwds ) : <EOL> element = etree . SubElement ( self . element , tagname , ** kwds ) <EOL> return XmlElement ( element , self . namespaces ) <EOL> def append ( self , elem ) : <EOL> if isinstance ( elem , XmlElement ) : <EOL> self . element . append ( elem . element ) <EOL> else : <EOL> self . element . append ( elem ) <EOL> def getparent ( self ) : <EOL> return XmlElement ( self . element . getparent ( ) , self . namespaces ) <EOL> def get_instance ( self , instance_class = None , fields = [ ] ) : <EOL> """<STR_LIT>""" <EOL> if not instance_class : <EOL> instance_class = Element <EOL> if not fields and hasattr ( instance_class , '<STR_LIT>' ) : <EOL> fields = instance_class . fields <EOL> if not fields : <EOL> instance = instance_class ( self . attrib , self ) <EOL> else : <EOL> instance = instance_class ( { } , self ) <EOL> for field in fields : <EOL> if field in self . attrib : <EOL> instance [ field ] = self . attrib [ field ] <EOL> return instance <EOL> def add_instance ( self , name , instance , fields = [ ] ) : <EOL> """<STR_LIT>""" <EOL> if not fields and hasattr ( instance , '<STR_LIT>' ) : <EOL> fields = instance . keys ( ) <EOL> elem = self . add_element ( name ) <EOL> for field in fields : <EOL> if field in instance and instance [ field ] : <EOL> elem . set ( field , unicode ( instance [ field ] ) ) <EOL> return elem <EOL> def remove_elements ( self , name ) : <EOL> """<STR_LIT>""" <EOL> if not element_name . startswith ( '<STR_LIT>' ) : <EOL> element_name = '<STR_LIT>' + element_name <EOL> elements = self . element . xpath ( '<STR_LIT>' % name , namespaces = self . namespaces ) <EOL> for element in elements : <EOL> parent = element . getparent ( ) <EOL> parent . remove ( element ) <EOL> def delete ( self ) : <EOL> parent = self . getparent ( ) <EOL> parent . remove ( self ) <EOL> def remove ( self , element ) : <EOL> if isinstance ( element , XmlElement ) : <EOL> self . element . remove ( element . element ) <EOL> else : <EOL> self . element . remove ( element ) <EOL> def set_text ( self , text ) : <EOL> self . element . text = text <EOL> def unset ( self , key ) : <EOL> del self . element . attrib [ key ] <EOL> def toxml ( self ) : <EOL> return etree . tostring ( self . element , encoding = '<STR_LIT>' , pretty_print = True ) <EOL> def __str__ ( self ) : <EOL> return self . toxml ( ) <EOL> def __getattr__ ( self , name ) : <EOL> if not hasattr ( self . element , name ) : <EOL> raise AttributeError , name <EOL> return getattr ( self . element , name ) <EOL> class XML : <EOL> def __init__ ( self , xml = None , namespaces = None ) : <EOL> self . root = None <EOL> self . namespaces = namespaces <EOL> self . default_namespace = None <EOL> self . schema = None <EOL> if isinstance ( xml , basestring ) : <EOL> self . parse_xml ( xml ) <EOL> if isinstance ( xml , XmlElement ) : <EOL> self . root = xml <EOL> self . namespaces = xml . namespaces <EOL> elif isinstance ( xml , etree . _ElementTree ) or isinstance ( xml , etree . _Element ) : <EOL> self . parse_xml ( etree . tostring ( xml ) ) <EOL> def parse_xml ( self , xml ) : <EOL> """<STR_LIT>""" <EOL> parser = etree . XMLParser ( remove_blank_text = True ) <EOL> print parser <EOL> print xml <EOL> try : <EOL> tree = etree . parse ( xml , parser ) <EOL> except IOError : <EOL> try : <EOL> tree = etree . parse ( StringIO ( xml ) , parser ) <EOL> print StringIO ( xml ) , xml <EOL> except Exception , e : <EOL> raise InvalidXML ( str ( e ) ) <EOL> root = tree . getroot ( ) <EOL> self . namespaces = dict ( root . nsmap ) <EOL> if '<STR_LIT:default>' not in self . namespaces and None in self . namespaces : <EOL> self . namespaces [ '<STR_LIT:default>' ] = self . namespaces . pop ( None ) <EOL> else : <EOL> self . namespaces [ '<STR_LIT:default>' ] = '<STR_LIT:default>' <EOL> self . root = XmlElement ( root , self . namespaces ) <EOL> for key in self . root . attrib . keys ( ) : <EOL> if key . endswith ( '<STR_LIT>' ) : <EOL> schema_parts = [ x for x in self . root . attrib [ key ] . split ( '<STR_LIT:U+0020>' ) if x ] <EOL> self . schema = schema_parts [ <NUM_LIT:1> ] <EOL> namespace , schema = schema_parts [ <NUM_LIT:0> ] , schema_parts [ <NUM_LIT:1> ] <EOL> break <EOL> def parse_dict ( self , d , root_tag_name = '<STR_LIT>' , element = None ) : <EOL> if element is None : <EOL> if self . root is None : <EOL> self . parse_xml ( '<STR_LIT>' % root_tag_name ) <EOL> element = self . root . element <EOL> if '<STR_LIT:text>' in d : <EOL> text = d . pop ( '<STR_LIT:text>' ) <EOL> element . text = text <EOL> for ( key , value ) in d . items ( ) : <EOL> if isinstance ( value , list ) : <EOL> value = d . pop ( key ) <EOL> for val in value : <EOL> if isinstance ( val , dict ) : <EOL> child_element = etree . SubElement ( element , key ) <EOL> self . parse_dict ( val , key , child_element ) <EOL> elif isinstance ( val , basestring ) : <EOL> child_element = etree . SubElement ( element , key ) . text = val <EOL> elif isinstance ( value , int ) : <EOL> d [ key ] = unicode ( d [ key ] ) <EOL> elif value is None : <EOL> d . pop ( key ) <EOL> d = d . copy ( ) <EOL> for k in d . keys ( ) : <EOL> if not isinstance ( d [ k ] , StringTypes ) : <EOL> del d [ k ] <EOL> element . attrib . update ( d ) <EOL> def validate ( self , schema ) : <EOL> """<STR_LIT>""" <EOL> relaxng_doc = etree . parse ( schema ) <EOL> relaxng = etree . RelaxNG ( relaxng_doc ) <EOL> if not relaxng ( self . root ) : <EOL> error = relaxng . error_log . last_error <EOL> message = "<STR_LIT>" % ( error . message , error . line ) <EOL> raise InvalidXML ( message ) <EOL> return True <EOL> def xpath ( self , xpath , namespaces = None ) : <EOL> if not namespaces : <EOL> namespaces = self . namespaces <EOL> return self . root . xpath ( xpath , namespaces = namespaces ) <EOL> def set ( self , key , value ) : <EOL> return self . root . set ( key , value ) <EOL> def remove_attribute ( self , name , element = None ) : <EOL> if not element : <EOL> element = self . root <EOL> element . remove_attribute ( name ) <EOL> def add_element ( self , * args , ** kwds ) : <EOL> """<STR_LIT>""" <EOL> return self . root . add_element ( * args , ** kwds ) <EOL> def remove_elements ( self , name , element = None ) : <EOL> """<STR_LIT>""" <EOL> if not element : <EOL> element = self . root <EOL> element . remove_elements ( name ) <EOL> def add_instance ( self , * args , ** kwds ) : <EOL> return self . root . add_instance ( * args , ** kwds ) <EOL> def get_instance ( self , * args , ** kwds ) : <EOL> return self . root . get_instnace ( * args , ** kwds ) <EOL> def get_element_attributes ( self , elem = None , depth = <NUM_LIT:0> ) : <EOL> if elem == None : <EOL> elem = self . root <EOL> if not hasattr ( elem , '<STR_LIT>' ) : <EOL> return elem <EOL> attrs = dict ( elem . attrib ) <EOL> attrs [ '<STR_LIT:text>' ] = str ( elem . text ) . strip ( ) <EOL> attrs [ '<STR_LIT>' ] = elem . getparent ( ) <EOL> if isinstance ( depth , int ) and depth > <NUM_LIT:0> : <EOL> for child_elem in list ( elem ) : <EOL> key = str ( child_elem . tag ) <EOL> if key not in attrs : <EOL> attrs [ key ] = [ self . get_element_attributes ( child_elem , depth - <NUM_LIT:1> ) ] <EOL> else : <EOL> attrs [ key ] . append ( self . get_element_attributes ( child_elem , depth - <NUM_LIT:1> ) ) <EOL> else : <EOL> attrs [ '<STR_LIT>' ] = list ( elem ) <EOL> return attrs <EOL> def append ( self , elem ) : <EOL> return self . root . append ( elem ) <EOL> def iterchildren ( self ) : <EOL> return self . root . iterchildren ( ) <EOL> def merge ( self , in_xml ) : <EOL> pass <EOL> def __str__ ( self ) : <EOL> return self . toxml ( ) <EOL> def toxml ( self ) : <EOL> return etree . tostring ( self . root . element , encoding = '<STR_LIT>' , pretty_print = True ) <EOL> def todict ( self , elem = None ) : <EOL> if elem is None : <EOL> elem = self . root <EOL> d = { } <EOL> d . update ( elem . attrib ) <EOL> d [ '<STR_LIT:text>' ] = elem . text <EOL> for child in elem . iterchildren ( ) : <EOL> if child . tag not in d : <EOL> d [ child . tag ] = [ ] <EOL> d [ child . tag ] . append ( self . todict ( child ) ) <EOL> if len ( d ) == <NUM_LIT:1> and ( "<STR_LIT:text>" in d ) : <EOL> d = d [ "<STR_LIT:text>" ] <EOL> return d <EOL> def save ( self , filename ) : <EOL> f = open ( filename , '<STR_LIT:w>' ) <EOL> f . write ( self . toxml ( ) ) <EOL> f . close ( ) </s>
