pyMez.Code.DataHandlers.XMLModels module
XMLModels is dedicated to handling xml based models, requires lxml to be installed.
#----------------------------------------------------------------------------- # Name: XMLModels.py # Purpose: To define XML models # Author: Aric Sanders # Created: 2/21/2016 # License: MIT License #----------------------------------------------------------------------------- """ XMLModels is dedicated to handling xml based models, requires lxml to be installed. """ #----------------------------------------------------------------------------- # Standard Imports import os import xml.dom # Xml document handling import xml.dom.minidom # For xml parsing from xml.dom.minidom import getDOMImplementation # Making blank XML documents import datetime import urlparse # To form proper URLs import socket # To determine IPs and Hosts from types import * # For Data Type testing #----------------------------------------------------------------------------- # Third Party Imports # For XLST transformations of the data try: from lxml import etree XSLT_CAPABLE=1 except: print("Transformations using XSLT are not available please check the lxml module") XSLT_CAPABLE=0 pass # For auto generation of common method aliases try: from pyMez.Code.Utils.Alias import * METHOD_ALIASES=1 except: print("The module pyMez.Code.Utils.Alias was not found") METHOD_ALIASES=0 pass # For Auto-naming of files if path is not specified try: from pyMez.Code.Utils.Names import auto_name DEFAULT_FILE_NAME=None except: print("The function auto_name in pyMez.Code.Utils.Names was not found") print("Setting Default file name to New_XML.xml") DEFAULT_FILE_NAME='New_XML.xml' pass # For retrieving metadata try: from pyMez.Code.Utils.Names import auto_name DEFAULT_FILE_NAME=None except: print("The function auto_name in pyMez.Code.Utils.Names was not found") print("Setting Default file name to New_XML.xml") DEFAULT_FILE_NAME='New_XML.xml' pass try: from pyMez.Code.Utils.GetMetadata import * except: print "Can not find the module GetMetadata, please add it to sys.path" print "Anything that uses the functions from GetMetadata will be broken" pass #----------------------------------------------------------------------------- # Module Constants XSLT_REPOSITORY='../XSL' TESTS_DIRECTORY=os.path.join(os.path.dirname(os.path.realpath(__file__)),'Tests') DRIVER_FILE_EXTENSIONS=['sys','SYS','drv','DRV'] NODE_TYPE_DICTIONARY={'1':'ELEMENT_NODE', '2':'ATTRIBUTE_NODE', '3':'TEXT_NODE', '4':'CDATA_SECTION_NODE', '6':'ENTITY_NODE', '7':'PROCESSING_INSTRUCTION_NODE', '8':'COMMENT_NODE','9':'DOCUMENT_NODE','10':'DOCUMENT_TYPE_NODE', '12':'NOTATION_NODE'} #----------------------------------------------------------------------------- # Module Functions def dictionary_to_xml(dictionary=None,char_between='\n'): string_output='' for key,value in dictionary.iteritems(): xml_open="<"+str(key)+">" xml_close="</"+str(key)+">" string_output=string_output+xml_open+str(value)+xml_close+char_between return string_output def dictionary_to_xmlchunk(dictionary, level='attribute'): "returns a string formatted as xml when given a python dictionary" if type(dictionary) is not dict:raise if re.match('attr',level,re.IGNORECASE): prefix="<Tuple " postfix=" />" inner="" for key,value in dictionary.iteritems(): inner=inner+"%s='%s' "%(key,value) xml_out=prefix+inner+postfix if re.match('tag',level,re.IGNORECASE): xml_out="" for key,value in dictionary.iteritems(): xml_out=xml_out+"<"+str(key)+">"+str(value)+"</"+str(key)+">" return xml_out def dictionary_list_to_xmlchunk(list_of_dictionaries,level='attribute'): """returns a string of xml given a list of dictionaries, level says if keys become attribute names or tag names""" if type(list_of_dictionaries) is not list:raise xml_out="" for item in list_of_dictionaries: xml_out=xml_out+dictionary_to_xmlchunk(item,level)+"\n" return xml_out def get_XML_text(tag_name,path=None,text=None): """ Returns the text in the first tag found with tag name """ if text is None: f=open(path,'r') text=f.read() tag_match=re.search( '<%s>(?P<XML_text>\w+)</%s>'%(tag_name,tag_name), text) return tag_match.group('XML_text') def URL_to_path(URL,form='string'): """Takes an URL and returns a path as form. Argument form may be 'string' or 'list'""" path=urlparse.urlparse(URL)[2] if form in ['string', 'str', 's']: return path elif form in ['list','ls','li']: path_list=path.split('/') return path_list def condition_URL(URL): """ Function that makes sure URL's have a / format and assigns host as local host if there is not one. Also gives paths a file protocol.""" parsed_URL=urlparse.urlparse(URL.replace('\\','/')) if not (parsed_URL[0] in ['file','http','ftp']): parsed_URL=urlparse.urlparse('file:'+URL.replace('\\','/')) return str(urlparse.urlunparse(parsed_URL).replace('///','')) #----------------------------------------------------------------------------- # Module Classes class XMLBase(): """ The XMLBase Class is designed to be a container for xml data """ def __init__(self,file_path=None,**options): "Initializes the XML Base Class " # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"root", "style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_STYLE.xsl').replace('\\','/'), "specific_descriptor":'XML', "general_descriptor":'Document', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value # Define Method Aliases if they are available if METHOD_ALIASES: for command in alias(self): exec(command) #if the file path is not supplied create a new xml sheet if file_path is None: impl=getDOMImplementation() self.document=impl.createDocument(None,self.options['root'],None) # Should be a relative path for new_node=self.document.createProcessingInstruction('xml-stylesheet', u'type="text/xsl" href="%s"'%self.options['style_sheet']) self.document.insertBefore(new_node,self.document.documentElement) if DEFAULT_FILE_NAME is None: self.path=auto_name(self.options["specific_descriptor"], self.options["general_descriptor"], self.options["directory"], self.options["extension"]) else: # Just a backup plan if the python path is messed up self.path=DEFAULT_FILE_NAME else: file_in=open(file_path,'r') self.document=xml.dom.minidom.parse(file_in) file_in.close() self.path=file_path def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close() if XSLT_CAPABLE: def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML) def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close() def show(self,mode='Window'): """ Displays a XML Document either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop() def __str__(self): "Controls how XMLBAse is returned when a string function is called" return self.document.toprettyxml() class XMLLog(XMLBase): """ Data container for a general XMLLog""" def __init__(self,file_path=None,**options): """ Intializes the XMLLog""" # We add the defaults for the log pass and the options along defaults={"root":'Log', 'style_sheet':os.path.join(XSLT_REPOSITORY,'DEFAULT_LOG_STYLE.xsl').replace('\\','/'), 'entry_style_sheet':os.path.join(XSLT_REPOSITORY,'DEFAULT_LOG_STYLE.xsl').replace('\\','/'), 'specific_descriptor':'XML','general_descriptor':'Log'} self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) # TODO: Check how scalable a dictionary of nodes is self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')]) self.current_entry={} def add_entry(self,entry=None): """ Adds an entry element to the current log""" root=self.document.documentElement if entry is None: new_entry=self.document.createElement('Entry') value='' elif type(entry) is str: if re.search('<Entry>(.)+</Entry>',entry): new_document=xml.dom.minidom.parseString(new_entry) new_entry=new_document.documentElement else: new_document=xml.dom.minidom.parseString('<Entry>' +entry+'</Entry>') new_entry=new_document.documentElement else: new_entry=entry # Find the max of Index's and add 1 to make a new Index if len(self.Index_node_dictionary)==0: new_Index='1' else: max_Index=max([int(Index) for Index in self.Index_node_dictionary.keys()]) new_Index=str(max_Index+1) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(new_Index)) if new_entry.getAttribute('Date'): pass else: # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() try: value=new_entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':new_entry.getAttribute('Index'), 'Date':new_entry.getAttribute('Date')} def edit_entry(self,old_Index,new_value=None,new_Index=None,new_Date=None): """Edits and existing entry by replacing the existing values with new ones""" node=self.get_entry(str(old_Index)) if not new_value is None: new_text_node=self.document.createTextNode(new_value) try: old_text_node=node.childNodes[0] node.removeChild(old_text_node) except: pass node.appendChild(new_text_node) elif not new_Index is None: node.setAttribute('Index',new_Index) elif not new_Date is None: node.setAttribute('Date',new_Date) self.current_entry={'Tag':'Entry','Value':node.childNodes[0].data,'Index':node.getAttribute('Index'), 'Date':node.getAttribute('Date')} def get_entry(self,Index): """ Returns the entry selcted by Index""" return self.Index_node_dictionary[str(Index)] def set_current_entry(self,Index=-1): """Sets self.current_entry """ entry=self.Index_node_dictionary[str(Index)] try: value=entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':entry.getAttribute('Index'), 'Date':entry.getAttribute('Date')} def remove_entry(self,Index): """ Removes the entry using the Index attribute""" root=self.document.documentElement root.removeChild(self.Index_node_dictionary[Index]) self.update_Index_node_dictionary() def add_description(self,description=None): """ Adds an entry with Index='-1' which holds data about the log itself""" root=self.document.documentElement new_entry=self.document.createElement('Entry') if not description is None: text_node=self.document.createTextNode(description) new_entry.appendChild(text_node) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(-1)) # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() def update_Index_node_dictionary(self): """ Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document""" self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')]) # if the XSLT engine loaded then define a transformation to HTML if XSLT_CAPABLE: def current_entry_to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: XSLT=self.options['entry_style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) current_entry_XML=self.Index_node_dictionary[self.current_entry['Index']] HTML=XSL_transform(etree.XML(current_entry_XML.toxml())) return HTML # TODO: Make show and display function work well def previous_entry(self): """Sets current entry to the one before""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index-1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if min(Indices)<Index: Indices.sort() new_Index=Indices[Indices.index(Index)-1] else: Indices.remove(Index) if len(Indices)>0: new_Index=max(Indices) else: new_Index=Index self.set_current_entry(new_Index) def next_entry(self): """Sets current entry to the one after""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index+1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if max(Indices)>Index: Indices.sort() new_Index=Indices[Indices.index(Index)+1] else: Indices.remove(Index) new_Index=min(Indices) self.set_current_entry(new_Index) def show(self,mode='text'): """ Displays a XMLLog either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop() def __add__(object,right): """Controls Behavior of two XMLLogs added using the + operator""" new_log=object for entry in right.document.getElementsByTagName('Entry'): if entry.getAttribute('Index')=='-1': pass else: new_log.add_entry(entry) return new_log class ChangeXMLLog(XMLLog): """ A XMLLog for storing changes to a program""" def __init__(self,path=None,program_name=None): XMLLog.__init__(self,path) # set the description element if it is a new log if path is None: self.add_ChangeXMLLog_description(program_name) def add_ChangeXMLLog_description(self,program_name=None): """ Adds a description of the change log as element Index=-1""" if program_name is None: program_name='a program' description="""This is a change log for %s. It consists of entries with a date attribute, an Index attribute that is a simple integer, and text describing the changes made to %s."""%(program_name,program_name) self.add_description(description) class EndOfDayXMLLog(XMLLog): """ A XMLLog for storing notes about daily activities""" def __init__(self,path=None): options={"style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_STYLE.xsl').replace('\\','/')} XMLLog.__init__(self,path,**options) if path is None: self.add_EndOfDayXMLLog_description() self.information_tags=['Actions','Who_Did','Who_Suggested','Why','Conclusion','Data_Location'] def add_entry_information(self,Index=None,**entry): """ Adds a log specific entry takes a dicitionary in the form {'tag':value,..} this does not add atributes""" if Index is None: self.add_entry() Index=self.current_entry['Index'] try: node=self.get_entry(Index) except: raise for tag,value in entry.iteritems(): new_element=self.document.createElement(tag) new_text=self.document.createTextNode(str(value)) new_element.appendChild(new_text) node.appendChild(new_element) def add_EndOfDayXMLLog_description(self,program_name=None): """ Adds a description of the log as element Index=-1""" description="""This is a End of day log. It consists of entries with a date attribute, an Index attribute that is a simple integer, and xml tags describing daily activities""" self.add_description(description) class ErrorXMLLog(XMLLog): """ A XMLLog for storring errors generated by a program """ def __init__(self,path=None): XMLLog.__init__(self,path) class ServiceXMLLog(XMLLog): """ A XMLLog for servicing an instrument or experiment """ def __init__(self,path=None,instrument_name=None): XMLLog.__init__(self,path) class DataTable(XMLBase): """ This is a XML data table class with an optional description""" def __init__(self,file_path=None,**options): """ Intializes the DataTable Class. Passing **{'data_table':[mylist]} creates a table with x1 and x2 as column names. Passing **{'data_dictionary':{'Data_Description':{'Tag':'Text',etc}, 'Data':[{'x':1,'y':2},{'x':2,'y':3}] """ # the general idea is <Data_Description/><Data><Tuple i=''/></Data> # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"Data_Table", "style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_MEASUREMENT_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Data', "general_descriptor":'Table', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) try: data_table=self.options['data_table'] if len(data_table)>0: data_node=self.list_to_XML(data_table) self.document.documentElement.appendChild(data_node) except: pass try: data_dictionary=self.options['data_dictionary'] if len(data_dictionary)>0: for key,value in data_dictionary.iteritems(): # This hanldes Tag:Text dictionaries if re.search('description',key,re.IGNORECASE): #This is the flat dictionary handling code {"Data_Description:{key:value}} #Need one that is {"Data_Description":{"Context":{key:value}}} new_entry=self.document.createElement(key) for tag,element_text in value.iteritems(): if type(element_text) is DictionaryType: new_tag=self.document.createElement(tag) new_entry.appendChild(new_tag) for inner_tag,inner_element_text in element_text.iteritems(): new_inner_tag=self.document.createElement(inner_tag) new_inner_text=self.document.createTextNode(inner_element_text) new_inner_tag.appendChild(new_inner_text) new_tag.appendChild(new_inner_tag) else: new_tag=self.document.createElement(tag) new_text=self.document.createTextNode(element_text) new_tag.appendChild(new_text) new_entry.appendChild(new_tag) self.document.documentElement.appendChild(new_entry) if re.search('data',key,re.IGNORECASE) and not re.search('Description',key,re.IGNORECASE): new_entry=self.list_to_XML(value) self.document.documentElement.appendChild(new_entry) except:pass def list_to_XML(self,data_list): """ Converts a list to XML document""" data_node=self.document.createElement('Data') #self.document.documentElement.appendChild(data_node) for row in data_list: if type(row) in [ListType,TupleType]: new_entry=self.document.createElement('Tuple') for j,datum in enumerate(row): x_attribute=self.document.createAttribute('X%s'%j) new_entry.setAttributeNode(x_attribute) new_entry.setAttribute('X%s'%j,str(datum)) data_node.appendChild(new_entry) elif type(row) is DictionaryType: new_entry=self.document.createElement('Tuple') for key,datum in row.iteritems(): x_attribute=self.document.createAttribute(key) new_entry.setAttributeNode(x_attribute) new_entry.setAttribute(key,str(datum)) data_node.appendChild(new_entry) return data_node def get_attribute_names(self): """ Returns the attribute names in the first tuple element in the 'data' element """ attribute_names=[] data_nodes=self.document.getElementsByTagName('Data') first_tuple_node=data_nodes[0].childNodes[1] text=first_tuple_node.toprettyxml() text_list=text.split(' ') #print text_list for item in text_list: try: match=re.search('(?P<attribute_name>\w+)=',item) name=match.group('attribute_name') #print name attribute_names.append(name) except:pass return attribute_names def to_list(self,attribute_name): """ Outputs the data as a list given a data column (attribute) name""" try: node_list=self.document.getElementsByTagName('Tuple') data_list=[node.getAttribute(attribute_name) for node in node_list] return data_list except: return None def to_tuple_list(self,attribute_names): """ Returns a list of tuples for the specified list of attribute names""" try: node_list=self.document.getElementsByTagName('Tuple') data_list=[tuple([node.getAttribute(attribute_name) for attribute_name in attribute_names]) for node in node_list] return data_list except: return None def get_header(self,style='txt'): """ Creates a header from the data description if there is one""" try: node_list=self.document.getElementsByTagName('Data_Description') data_description=node_list[0] out='' if style in ['txt','text','ascii']: for child in data_description.childNodes: try: out=out+'%s: %s'%(child.nodeName,child.firstChild.nodeValue)+'\n' except:pass return out elif re.search('xml',style,flags=re.IGNORECASE): out=data_description.toprettyxml() return out except: raise class FileRegister(XMLBase): """ The base class for arbitrary database, which processes the File Register XML File.""" def __init__(self,file_path=None,**options): """ Initializes the File Register Class.""" # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"File_Registry", "style_sheet":os.path.join(XSLT_REPOSITORY,'FR_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Resource', "general_descriptor":'Registry', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')]) def create_Id(self,URL): """ Creates or returns the existing Id element of a URL""" parsed_URL=urlparse.urlparse(condition_URL(URL)) try: # Look in self.Id_dictionary, if it is not there catch # the exception KeyError and generate an Id. return self.Id_dictionary[URL.replace('///','')] except KeyError: # The Id is not in the existing list so start buliding Id. # Determine the IP Address of the host in the URL if parsed_URL[1] in ['',u'']: #if it is empty assume local host IP_address=socket.gethostbyaddr(socket.gethostname())[2][0] else: IP_address= socket.gethostbyaddr(parsed_URL[1])[2][0] Id_cache={} # We begin with all the entries with the same IP address for (key,value) in self.Id_dictionary.iteritems(): if value.startswith(IP_address): Id_cache[key]=value # If the Id_cache is empty then we just assign the number temp_Id=IP_address path_list=parsed_URL[2].split('/') file_extension=path_list[-1].split('.')[-1] if len(Id_cache) is 0: for index,part in enumerate(path_list): if index<len(path_list)-1: temp_Id=temp_Id+'.'+'11' elif index==len(path_list)-1: if (file_extension in DRIVER_FILE_EXTENSIONS): temp_Id=temp_Id+'.'+'31' elif os.path.isdir(parsed_URL[2]): temp_Id=temp_Id+'.'+'11' else: temp_Id=temp_Id+'.'+'21' return temp_Id # if it is not empty we have to a little work # remove the information about IP address place=0 #print path_list while place<=len(path_list): # If the Id_cache is empty assign the rest of the Id. if len(Id_cache) is 0: for index,part in enumerate(path_list[place:]): if index<len(path_list[place:])-1: temp_Id=temp_Id+'.'+'11' elif index==len(path_list[place:])-1: if (file_extension in DRIVER_FILE_EXTENSIONS): temp_Id=temp_Id+'.'+'31' elif os.path.isdir(parsed_URL[2]): temp_Id=temp_Id+'.'+'11' else: temp_Id=temp_Id+'.'+'21' return temp_Id # If the Id_cache is not empty else: path_cache=dict([(URL,URL_to_path(URL,form='list')) for URL in Id_cache.keys()]) print Id_cache part_cache=dict([(URL,[path_cache[URL][place], Id_cache[URL].split('.')[place+4]]) for URL in Id_cache.keys()]) parts_list=[part_cache[URL][0]for URL in Id_cache.keys()] node_number=max([int(Id_cache[URL].split('.')[place+4][1:]) for URL in Id_cache.keys()]) # If it is the last place if place==len(path_list)-1: new_node_number=node_number+1 if (file_extension in DRIVER_FILE_EXTENSIONS): new_node_type='3' elif os.path.isdir(parsed_URL[2]): new_node_type='1' else: new_node_type='2' temp_Id=temp_Id+'.'+new_node_type+str(new_node_number) return temp_Id # If it is not the last place assume it is a directory else: new_node_type='1' # Check to see if it is already in the FR if path_list[place] in parts_list: for URL in Id_cache.keys(): if part_cache[URL][0]==path_list[place]: new_node=part_cache[URL][1] # If not add one to node else: new_node_number=node_number+1 new_node=new_node_type+str(new_node_number) temp_Id=temp_Id+'.'+new_node # Update the Id_cache for the next round, and the place for URL in Id_cache.keys(): try: if not part_cache[URL][0]==path_list[place]: del(Id_cache[URL]) Id_cache[URL].split('.')[place+5] except KeyError: pass except IndexError: #print Id_cache,URL del(Id_cache[URL]) place=place+1 def add_entry(self,URL): """ Adds an entry to the current File Register """ URL=condition_URL(URL) if URL in self.Id_dictionary.keys(): print 'Already there' return # the xml entry is <File Date="" Host="" Type="" Id="" URL=""/> File_Registry=self.document.documentElement new_entry=self.document.createElement('File') # Make all the new attributes attributes=['Id','Host','Date','URL','Type'] new_attributes=dict([(attribute, self.document.createAttribute(attribute)) for attribute in \ attributes]) # Add the new attributes to the new entry for attribute in attributes: new_entry.setAttributeNode(new_attributes[attribute]) # Now assign the values attribute_values={} attribute_values['URL']=URL attribute_values['Id']=self.create_Id(URL) attribute_values['Date']=datetime.datetime.utcnow().isoformat() type_code=attribute_values['Id'].split('.')[-1][0] if type_code in ['1',u'1']: attribute_values['Type']="Directory" elif type_code in ['2',u'2']: attribute_values['Type']="Ordinary" elif type_code in ['3',u'3']: attribute_values['Type']="Driver" else: attribute_values['Type']="Other" parsed_URL=urlparse.urlparse(condition_URL(URL)) if parsed_URL[1] in ['',u'']: #if it is empty assume local host attribute_values['Host']= socket.gethostbyaddr(socket.gethostname())[0] else: attribute_values['Host']= parsed_URL[1] # Now set them all in the actual attribute for (key,value) in attribute_values.iteritems(): new_entry.setAttribute(key,value) File_Registry.appendChild(new_entry) # Finally update the self.Id_dictionary # Added boolean switch to speed up adding a lot of entries self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')]) # TODO : Add an input filter that guesses at what you inputed def add_tree(self,root,**options): """ Adds a directory and all sub folders and sub directories, **options provides a way to {'ignore','.pyc|etc'} or {'only','.png|.bmp'}""" # Deal with the optional parameters, these tend to make life easier default_options={'ignore':None,'only':None,'print_ignored_files':True, 'directories_only':False,'files_only':False} tree_options=default_options for option,value in options.iteritems(): tree_options[option]=value #print tree_options #condition the URL root_URL=condition_URL(root) path=URL_to_path(root_URL) # now we add the files and directories that jive with the options try: for (home,directories,files) in os.walk(path): #print (home,directories,files) for directory in directories:# had to change this, used to be first element in list try: if tree_options['files_only']: if tree_options['print_ignored_files']: print "ignoring %s because it is not a file"%file raise if tree_options['ignore'] is not None and re.search(tree_options['ignore'],directory): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%directory raise elif tree_options['only'] is not None and not re.search(tree_options['only'],directory): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%directory raise else: self.add_entry(condition_URL(os.path.join(home,directory))) self.save() except:pass for file in files: # had to change this 12/2012, used to be Second element in list try: if tree_options['directories_only']: if tree_options['print_ignored_files']: print "ignoring %s because it is not a directory"%file raise if tree_options['ignore'] is not None and re.search(tree_options['ignore'],file): if tree_options['print_ignored_files']: print "ignoring %s because it matches the ignore option"%file raise elif tree_options['only'] is not None and not re.search(tree_options['only'],file): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%file raise else: #print (home,file) self.add_entry(condition_URL(os.path.join(home,file))) self.save() except:raise except: raise #After all the files are added update the Id_dictionary self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')]) def remove_entry(self,URL=None,Id=None): """ Removes an entry in the current File Register """ File_Registry=self.document.documentElement if not URL is None: URL=condition_URL(URL) URL_FileNode_dictionary=dict([(node.getAttribute('URL'), node) for node in self.document.getElementsByTagName('File')]) File_Registry.removeChild(URL_FileNode_dictionary[URL]) else: Id_FileNode_dictionary=dict([(node.getAttribute('Id'), node) for node in self.document.getElementsByTagName('File')]) File_Registry.removeChild(Id_FileNode_dictionary[Id]) # Finally update the self.Id_dictionary self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in \ self.document.getElementsByTagName('File')]) class Metadata(XMLBase): """ Metadata holds the metadata tags for a FileRegistry, If it already exists and the parser gives an error check the xml file for special characters like """ def __init__(self,file_path=None,**options):#FileRegistry,Metadata_File=None) """ Intializes the class Metadata""" # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"Metadata_Registry", "style_sheet":os.path.join(XSLT_REPOSITORY,'METADATA_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Metadata', "general_descriptor":'Registry', "directory":None, "extension":'xml', "metadata_file":None } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value FileRegistry=file_path Metadata_File=self.options['metadata_file'] # Process the file register if type(FileRegistry) is InstanceType: self.FileRegister=FileRegistry elif type(FileRegistry) in StringTypes: self.FileRegister=FileRegister(FileRegistry) # Process or create the Metadata File if Metadata_File is None: # Make the metadata file based on the file register FileRegister_path=self.FileRegister.path.replace('\\','/') FileRegister_name=FileRegister_path.split('/')[-1] FileRegister_ext=FileRegister_name.split('.')[-1] Metadata_name=FileRegister_name.replace('.'+FileRegister_ext, '_Metadata.'+FileRegister_ext) self.path=FileRegister_path.replace(FileRegister_name,Metadata_name) self.document=self.FileRegister.document # delete old processing instructions for node in self.document.childNodes: if node.nodeType is 7: self.document.removeChild(node) node.unlink() # add in the default xsl new_node=self.document.createProcessingInstruction( 'xml-stylesheet', u'type="text/xsl" href="%s"'%self.options['style_sheet']) self.document.insertBefore(new_node,self.document.documentElement) # make sure there is a fileregister reference FR_Path=self.FileRegister.path new_node=self.document.createProcessingInstruction(\ 'xml-FileRegistry',\ 'href=\"%s\"'%(self.FileRegister.path)) self.document.insertBefore(new_node,self.document.documentElement) else: # The metadata file exists as a saved file or an instance if type(Metadata_File) is InstanceType: self.document=Metadata_File.document self.path=Metadata_File.path elif type(Metadata_File) in StringTypes: XMLBase.__init__(self,file_path,**self.options) # TODO: This dictionary of nodes worries me-- it may not scale well self.node_dictionary=dict([(str(node.getAttribute('URL')), node) for node in self.document.getElementsByTagName('File')]) self.URL_dictionary=dict([(str(node.getAttribute('Id')), str(node.getAttribute('URL'))) for node in self.document.getElementsByTagName('File')]) self.name_dictionary=dict([(Id,os.path.split(self.URL_dictionary[Id])[1]) for Id in self.URL_dictionary.keys()]) self.current_node=self.node_dictionary.values()[0] def search_name(self,name=None,re_flags=re.IGNORECASE): """ Returns a list of URL's that have an element matching name""" try: if re_flags in [None,'']: urls=filter(lambda x: re.search(name,x), self.URL_dictionary.values()) return urls else: urls=filter(lambda x: re.search(name,x,flags=re_flags), self.URL_dictionary.values()) return urls except: raise if XSLT_CAPABLE: def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return HTML def get_file_node(self,URL=None,Id=None): """ Returns the file node specified by URL or Id""" if not URL is None: URL=condition_URL(URL) self.current_node=self.node_dictionary[URL] return self.current_node elif not Id is None: self.current_node=self.node_dictionary[self.URL_dictionary[Id]] return self.current_node def set_current_node(self,URL=None,Id=None): """ Sets the current file node to the one specified by URL or Id""" if not URL is None: URL=condition_URL(URL) self.current_node=self.node_dictionary[URL] elif not Id is None: self.current_node=self.node_dictionary[self.URL_dictionary[Id]] def add_element_to_current_node(self,XML_tag=None,value=None,node=None,**Atributes): """Adds a metadata element to the current file node""" if node is None: new_element=self.document.createElement(XML_tag) else: new_element=node if not value is None: new_text=self.document.createTextNode(str(value)) new_element.appendChild(new_text) attributes=[key for key in Atributes.keys()] new_attributes=dict([(attribute, self.document.createAttribute(attribute)) for attribute in \ attributes]) for (key,value) in Atributes.iteritems(): new_element.setAttribute(key,str(value)) self.current_node.appendChild(new_element) def remove_element_in_current_node(self,element_name): """Removes all metadata elements with the same tagname in the current file node""" nodes_to_remove=self.current_node.getElementsByTagName(element_name) try: for node in nodes_to_remove: self.current_node.removeChild(node) except:pass if XSLT_CAPABLE: def current_node_to_HTML(self,XSLT=None): """Returns a HTML document from the current node""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.current_node.toxml())) return HTML def print_current_node(self): """ Prints the current node """ print self.current_node.toxml() #----------------------------------------------------------------------------- # Module Scripts def test_XMLModel(test_new=True,test_existing=False): """ a test of the XMLBase class """ if test_new: print("Begin Test of a New XML sheet \n") os.chdir(TESTS_DIRECTORY) new_xml=XMLBase(None,**{'style_sheet':'../XSL/DEFAULT_STYLE.xsl'}) print("The New Sheet has been created as new_xml \n") print('*'*80) print("The New File Path is {0}".format(os.path.join(TESTS_DIRECTORY,new_xml.path))) print('*'*80) print("The result of print new_xml") print(new_xml) print('*'*80) print("The result of new_xml.to_HTML()") print new_xml.to_HTML() print('*'*80) print("The result of new_xml.options") print new_xml.options print('*'*80) print("The new_xml has been saved") new_xml.save() if test_existing: print("Begin Test of a Preexisting XML sheet \n") os.chdir(TESTS_DIRECTORY) new_xml=XMLBase('Data_Table_021311_1.xml',**{'style_sheet':'../XSL/DEFAULT_STYLE.xsl'}) print("The New Sheet has been created as new_xml \n") print('*'*80) print("The New File Path is {0}".format(os.path.join(TESTS_DIRECTORY,new_xml.path))) print('*'*80) print("The result of print new_xml") print(new_xml) print('*'*80) print("The result of new_xml.to_HTML()") print new_xml.to_HTML() print('*'*80) print("The result of new_xml.options") print new_xml.options print('*'*80) print("The new_xml has been saved") new_xml.save() def test_XMLLog(): print('Creating New Log..\n') os.chdir(TESTS_DIRECTORY) new_log=XMLLog() print('Log Contents Upon Creation: using print new_log') print(new_log) print('\n') print('The New Log\'s path is %s'%new_log.path) print('Add an entry using new_log.add_entry("This is a test")') new_log.add_entry("This is a test") print('Log Contents: using print new_log') new_log.save() print(new_log) def test_log_addition(): """ Script to develop test the __add__ attribute for the class XMLLog""" # First we want to know how a copy works os.chdir(TESTS_DIRECTORY) import time log_1=XMLLog() log_1.add_entry("I am Log Number One") time.sleep(.3) log_2=XMLLog() log_2.add_entry("I am Log Number 2") print('Log_1 Contents: using print') print log_1 print('Log_2 Contents: using print') print log_2 print('Log_1+Log_2 Contents: using print') print log_1+log_2 def test_EndOfDayXMLLog(): """ Script to test that daily logs work properly""" os.chdir(TESTS_DIRECTORY) print('Creating New Log..\n') new_log=EndOfDayXMLLog() print('Log Contents Upon Creation: using print new_log') print(new_log) print('\n') print('The New Log\'s path is %s'%new_log.path) print('Add an entry using new_log.add_entry("This is a test")') new_log.add_entry("This is a test") print('Add an entry using new_log.add_entry_information(1,dictionary)') dictionary={'Actions':'I tested EndofDayLog()','Who_Did':'Aric Sanders' ,'Who_Suggested':'Small Green Man','Why':'To make sure it works!', 'Conclusion':'It Does!','Data_Location':'In front of your face'} new_log.add_entry_information(0,**dictionary) print('Log Contents: using print new_log') new_log.save() print(new_log) #new_log.show('wx') def test_show(): "Tests the show() method of the XMLLog class" os.chdir(TESTS_DIRECTORY) new_log=XMLLog() print 'New Log Created...' print 'The Result of Show() is:' print '*'*80 entries=['1','2','Now I see!', 'Today was a good day'] for entry in entries: new_log.add_entry(entry) print new_log.show() print '\n'*4 print 'The Result of XMLLog.show(xml) is:' print '*'*80 print new_log.show('xml') #the window version new_log.show('wx') def test_to_HTML(): "Tests the to_HTML method of the XMLLog class" os.chdir(TESTS_DIRECTORY) new_log=XMLLog() print 'New Log Created...' print 'The Result of Show() is:' print '*'*80 entries=['1','2','Now I see!', 'Today was a good day'] for entry in entries: new_log.add_entry(entry) print new_log.show() print '\n'*4 print 'The Result of XMLLog.to_HTML(xml) is:' print '*'*80 print new_log.to_HTML() def test_DataTable(): """ Tests the DataTable Class""" test_data=[tuple([2*i+j for i in range(3)]) for j in range(5)] test_options={'data_table':test_data} new_table=DataTable(None,**test_options) print new_table test_dictionary={'Data_Description':{'x':'X Distance in microns.', 'y':'y Distance in microns.','Notes':'This data is fake'},'Data':[[1,2],[2,3]]} test_dictionary_2={'Data_Description':{'x':'x Distance in microns.', 'y':'y Distance in microns.'},'Data':[{'x':1,'y':2},{'x':2,'y':3}]} test_dictionary_3={'Data_Description':{'Column_Descriptions':{'x':'x Distance in microns.', 'y':'y Distance in microns.'}},'Data':[{'x':1,'y':2},{'x':2,'y':3}]} test_options_2={'data_dictionary':test_dictionary} test_options_3={'data_dictionary':test_dictionary_2} test_options_4={'data_dictionary':test_dictionary_3} new_table_2=DataTable(**test_options_2) new_table_3=DataTable(**test_options_3) new_table_4=DataTable(**test_options_4) print new_table_2 print new_table_3 print new_table_3.to_list('x') print new_table_3.to_tuple_list(['x','y']) print new_table_3.path new_table_3.get_header() print new_table_4 def test_get_header(): """ Test of the get header function of the DataTable Class """ test_dictionary={'Data_Description':{'x':'X Distance in microns.', 'y':'y Distance in microns.','Notes':'This data is fake'},'Data':[[1,2],[2,3]]} new_table=DataTable(**{'data_dictionary':test_dictionary}) header=new_table.get_header() print header print new_table.get_header('xml') def test_open_measurement(sheet_name='Data_Table_021311_1.xml'): """Tests opening a sheet""" os.chdir(TESTS_DIRECTORY) measurement=DataTable(sheet_name) print("The file path is {0}".format(measurement.path)) #print measurement print measurement.get_header() def test_get_attribute_names(sheet_name='Data_Table_021311_1.xml'): "Tests the get_attribute_name method of the DataTable Class" os.chdir(TESTS_DIRECTORY) measurement=DataTable(sheet_name) names=measurement.get_attribute_names() print 'the names list is:',names print 'Using the names list to create a data table:' print '*'*80+'\n'+'%s %s %s'%(names[0], names[1], names[2])+'\n'+'*'*80 for index,item in enumerate(measurement.to_list(names[0])): row='' for name in names: row=measurement.to_list(name)[index] +'\t'+row print row def test_FileRegister(): "Tests the FileRegister Class" os.chdir(TESTS_DIRECTORY) new_file_register=FileRegister() new_file_register.add_tree(os.getcwd()) print new_file_register def test_Metadata(File_Registry=None,Metadata_File=None): os.chdir(TESTS_DIRECTORY) if File_Registry is None: File_Registry=os.path.join(TESTS_DIRECTORY,'Resource_Registry_20160222_001.xml') options={'file_registry':File_Registry} new_Metadata=Metadata(None,**options) print new_Metadata.current_node_to_HTML() #new_Metadata.save() def metadata_robot(file_registry=None,metadata=None): """ This robot checks for system metadata for the files in file_register and adds them to metadata without repeats (first removes old data with the same tagname). If no metadata file is given it just writes them to a file in the same folder as file_register""" if file_registry is None: os.chdir(TESTS_DIRECTORY) file_registry=r'Resource_Registry_20160518_001.xml' file_register=FileRegister(file_registry) if metadata is None: metadata_file=Metadata(file_register,**{"metadata_file":metadata}) else: metadata_file=Metadata(file_register,**{"metadata_file":metadata}) for URL in metadata_file.FileRegister.Id_dictionary.keys(): try: system_metadata=get_system_metadata(URL_to_path(URL)) metadata_file.get_file_node(URL) metadata_file.remove_element_in_current_node('System_Metadata') metadata_file.add_element_to_current_node(XML_tag='System_Metadata',**system_metadata) except: print 'No system metadata for %s'%URL pass try: file_metadata=get_file_metadata(URL_to_path(URL)) new_file_info_node=metadata_file.document.createElement('File_Metadata') for key,value in file_metadata.iteritems(): new_node=metadata_file.document.createElement(key) new_text=metadata_file.document.createTextNode(str(value)) new_node.appendChild(new_text) new_file_info_node.appendChild(new_node) metadata_file.remove_element_in_current_node('File_Metadata') metadata_file.add_element_to_current_node(node=new_file_info_node) except: print 'no file data for %s'%URL pass try: image_metadata=get_image_metadata(URL_to_path(URL)) if not image_metadata is None: new_image_info_node=metadata_file.document.createElement('Image_Metadata') for key,value in image_metadata.iteritems(): new_node=metadata_file.document.createElement(key) print key,str(value) print str(value) in ['','',chr(30)] new_text=metadata_file.document.createTextNode(str(value).replace(chr(30),'')) new_node.appendChild(new_text) new_image_info_node.appendChild(new_node) metadata_file.remove_element_in_current_node('Image_Metadata') metadata_file.add_element_to_current_node(node=new_image_info_node) print ' Image data' except: print 'no image metadata for %s'%URL pass try: python_metadata=get_python_metadata(URL_to_path(URL)) #print python_metadata metadata_file.get_file_node(URL) metadata_file.remove_element_in_current_node('Python_Docstring') metadata_file.add_element_to_current_node(XML_tag='Python_Docstring', value=str(python_metadata['Python_Docstring'])) except:pass metadata_file.save() #----------------------------------------------------------------------------- # Module Runner if __name__=='__main__': #test_XMLModel() #test_XMLLog() #test_log_addition() #test_EndOfDayXMLLog() #test_show() #test_to_HTML() #test_DataTable() #test_get_header() #test_open_measurement() #test_get_attribute_names() #test_FileRegister() #test_Metadata() metadata_robot()
Module variables
var DEFAULT_FILE_NAME
var DRIVER_FILE_EXTENSIONS
var EXIF_AVAILABLE
var GET_STATS_FIELDS
var IMAGE_FILE_EXTENSIONS
var METHOD_ALIASES
var NODE_TYPE_DICTIONARY
var OS_STAT_FIELDS
var PIL_AVAILABLE
var StringTypes
var TESTS_DIRECTORY
var XSLT_CAPABLE
var XSLT_REPOSITORY
Functions
def URL_to_path(
URL, form='string')
Takes an URL and returns a path as form. Argument form may be 'string' or 'list'
def URL_to_path(URL,form='string'): """Takes an URL and returns a path as form. Argument form may be 'string' or 'list'""" path=urlparse.urlparse(URL)[2] if form in ['string', 'str', 's']: return path elif form in ['list','ls','li']: path_list=path.split('/') return path_list
def condition_URL(
URL)
Function that makes sure URL's have a / format and assigns host as local host if there is not one. Also gives paths a file protocol.
def condition_URL(URL): """ Function that makes sure URL's have a / format and assigns host as local host if there is not one. Also gives paths a file protocol.""" parsed_URL=urlparse.urlparse(URL.replace('\\','/')) if not (parsed_URL[0] in ['file','http','ftp']): parsed_URL=urlparse.urlparse('file:'+URL.replace('\\','/')) return str(urlparse.urlunparse(parsed_URL).replace('///',''))
def dictionary_list_to_xmlchunk(
list_of_dictionaries, level='attribute')
returns a string of xml given a list of dictionaries, level says if keys become attribute names or tag names
def dictionary_list_to_xmlchunk(list_of_dictionaries,level='attribute'): """returns a string of xml given a list of dictionaries, level says if keys become attribute names or tag names""" if type(list_of_dictionaries) is not list:raise xml_out="" for item in list_of_dictionaries: xml_out=xml_out+dictionary_to_xmlchunk(item,level)+"\n" return xml_out
def dictionary_to_xml(
dictionary=None, char_between='\n')
def dictionary_to_xml(dictionary=None,char_between='\n'): string_output='' for key,value in dictionary.iteritems(): xml_open="<"+str(key)+">" xml_close="</"+str(key)+">" string_output=string_output+xml_open+str(value)+xml_close+char_between return string_output
def dictionary_to_xmlchunk(
dictionary, level='attribute')
returns a string formatted as xml when given a python dictionary
def dictionary_to_xmlchunk(dictionary, level='attribute'): "returns a string formatted as xml when given a python dictionary" if type(dictionary) is not dict:raise if re.match('attr',level,re.IGNORECASE): prefix="<Tuple " postfix=" />" inner="" for key,value in dictionary.iteritems(): inner=inner+"%s='%s' "%(key,value) xml_out=prefix+inner+postfix if re.match('tag',level,re.IGNORECASE): xml_out="" for key,value in dictionary.iteritems(): xml_out=xml_out+"<"+str(key)+">"+str(value)+"</"+str(key)+">" return xml_out
def get_XML_text(
tag_name, path=None, text=None)
Returns the text in the first tag found with tag name
def get_XML_text(tag_name,path=None,text=None): """ Returns the text in the first tag found with tag name """ if text is None: f=open(path,'r') text=f.read() tag_match=re.search( '<%s>(?P<XML_text>\w+)</%s>'%(tag_name,tag_name), text) return tag_match.group('XML_text')
def metadata_robot(
file_registry=None, metadata=None)
This robot checks for system metadata for the files in file_register and adds them to metadata without repeats (first removes old data with the same tagname). If no metadata file is given it just writes them to a file in the same folder as file_register
def metadata_robot(file_registry=None,metadata=None): """ This robot checks for system metadata for the files in file_register and adds them to metadata without repeats (first removes old data with the same tagname). If no metadata file is given it just writes them to a file in the same folder as file_register""" if file_registry is None: os.chdir(TESTS_DIRECTORY) file_registry=r'Resource_Registry_20160518_001.xml' file_register=FileRegister(file_registry) if metadata is None: metadata_file=Metadata(file_register,**{"metadata_file":metadata}) else: metadata_file=Metadata(file_register,**{"metadata_file":metadata}) for URL in metadata_file.FileRegister.Id_dictionary.keys(): try: system_metadata=get_system_metadata(URL_to_path(URL)) metadata_file.get_file_node(URL) metadata_file.remove_element_in_current_node('System_Metadata') metadata_file.add_element_to_current_node(XML_tag='System_Metadata',**system_metadata) except: print 'No system metadata for %s'%URL pass try: file_metadata=get_file_metadata(URL_to_path(URL)) new_file_info_node=metadata_file.document.createElement('File_Metadata') for key,value in file_metadata.iteritems(): new_node=metadata_file.document.createElement(key) new_text=metadata_file.document.createTextNode(str(value)) new_node.appendChild(new_text) new_file_info_node.appendChild(new_node) metadata_file.remove_element_in_current_node('File_Metadata') metadata_file.add_element_to_current_node(node=new_file_info_node) except: print 'no file data for %s'%URL pass try: image_metadata=get_image_metadata(URL_to_path(URL)) if not image_metadata is None: new_image_info_node=metadata_file.document.createElement('Image_Metadata') for key,value in image_metadata.iteritems(): new_node=metadata_file.document.createElement(key) print key,str(value) print str(value) in ['','',chr(30)] new_text=metadata_file.document.createTextNode(str(value).replace(chr(30),'')) new_node.appendChild(new_text) new_image_info_node.appendChild(new_node) metadata_file.remove_element_in_current_node('Image_Metadata') metadata_file.add_element_to_current_node(node=new_image_info_node) print ' Image data' except: print 'no image metadata for %s'%URL pass try: python_metadata=get_python_metadata(URL_to_path(URL)) #print python_metadata metadata_file.get_file_node(URL) metadata_file.remove_element_in_current_node('Python_Docstring') metadata_file.add_element_to_current_node(XML_tag='Python_Docstring', value=str(python_metadata['Python_Docstring'])) except:pass metadata_file.save()
def test_DataTable(
)
Tests the DataTable Class
def test_DataTable(): """ Tests the DataTable Class""" test_data=[tuple([2*i+j for i in range(3)]) for j in range(5)] test_options={'data_table':test_data} new_table=DataTable(None,**test_options) print new_table test_dictionary={'Data_Description':{'x':'X Distance in microns.', 'y':'y Distance in microns.','Notes':'This data is fake'},'Data':[[1,2],[2,3]]} test_dictionary_2={'Data_Description':{'x':'x Distance in microns.', 'y':'y Distance in microns.'},'Data':[{'x':1,'y':2},{'x':2,'y':3}]} test_dictionary_3={'Data_Description':{'Column_Descriptions':{'x':'x Distance in microns.', 'y':'y Distance in microns.'}},'Data':[{'x':1,'y':2},{'x':2,'y':3}]} test_options_2={'data_dictionary':test_dictionary} test_options_3={'data_dictionary':test_dictionary_2} test_options_4={'data_dictionary':test_dictionary_3} new_table_2=DataTable(**test_options_2) new_table_3=DataTable(**test_options_3) new_table_4=DataTable(**test_options_4) print new_table_2 print new_table_3 print new_table_3.to_list('x') print new_table_3.to_tuple_list(['x','y']) print new_table_3.path new_table_3.get_header() print new_table_4
def test_EndOfDayXMLLog(
)
Script to test that daily logs work properly
def test_EndOfDayXMLLog(): """ Script to test that daily logs work properly""" os.chdir(TESTS_DIRECTORY) print('Creating New Log..\n') new_log=EndOfDayXMLLog() print('Log Contents Upon Creation: using print new_log') print(new_log) print('\n') print('The New Log\'s path is %s'%new_log.path) print('Add an entry using new_log.add_entry("This is a test")') new_log.add_entry("This is a test") print('Add an entry using new_log.add_entry_information(1,dictionary)') dictionary={'Actions':'I tested EndofDayLog()','Who_Did':'Aric Sanders' ,'Who_Suggested':'Small Green Man','Why':'To make sure it works!', 'Conclusion':'It Does!','Data_Location':'In front of your face'} new_log.add_entry_information(0,**dictionary) print('Log Contents: using print new_log') new_log.save() print(new_log)
def test_FileRegister(
)
Tests the FileRegister Class
def test_FileRegister(): "Tests the FileRegister Class" os.chdir(TESTS_DIRECTORY) new_file_register=FileRegister() new_file_register.add_tree(os.getcwd()) print new_file_register
def test_Metadata(
File_Registry=None, Metadata_File=None)
def test_Metadata(File_Registry=None,Metadata_File=None): os.chdir(TESTS_DIRECTORY) if File_Registry is None: File_Registry=os.path.join(TESTS_DIRECTORY,'Resource_Registry_20160222_001.xml') options={'file_registry':File_Registry} new_Metadata=Metadata(None,**options) print new_Metadata.current_node_to_HTML()
def test_XMLLog(
)
def test_XMLLog(): print('Creating New Log..\n') os.chdir(TESTS_DIRECTORY) new_log=XMLLog() print('Log Contents Upon Creation: using print new_log') print(new_log) print('\n') print('The New Log\'s path is %s'%new_log.path) print('Add an entry using new_log.add_entry("This is a test")') new_log.add_entry("This is a test") print('Log Contents: using print new_log') new_log.save() print(new_log)
def test_XMLModel(
test_new=True, test_existing=False)
a test of the XMLBase class
def test_XMLModel(test_new=True,test_existing=False): """ a test of the XMLBase class """ if test_new: print("Begin Test of a New XML sheet \n") os.chdir(TESTS_DIRECTORY) new_xml=XMLBase(None,**{'style_sheet':'../XSL/DEFAULT_STYLE.xsl'}) print("The New Sheet has been created as new_xml \n") print('*'*80) print("The New File Path is {0}".format(os.path.join(TESTS_DIRECTORY,new_xml.path))) print('*'*80) print("The result of print new_xml") print(new_xml) print('*'*80) print("The result of new_xml.to_HTML()") print new_xml.to_HTML() print('*'*80) print("The result of new_xml.options") print new_xml.options print('*'*80) print("The new_xml has been saved") new_xml.save() if test_existing: print("Begin Test of a Preexisting XML sheet \n") os.chdir(TESTS_DIRECTORY) new_xml=XMLBase('Data_Table_021311_1.xml',**{'style_sheet':'../XSL/DEFAULT_STYLE.xsl'}) print("The New Sheet has been created as new_xml \n") print('*'*80) print("The New File Path is {0}".format(os.path.join(TESTS_DIRECTORY,new_xml.path))) print('*'*80) print("The result of print new_xml") print(new_xml) print('*'*80) print("The result of new_xml.to_HTML()") print new_xml.to_HTML() print('*'*80) print("The result of new_xml.options") print new_xml.options print('*'*80) print("The new_xml has been saved") new_xml.save()
def test_get_attribute_names(
sheet_name='Data_Table_021311_1.xml')
Tests the get_attribute_name method of the DataTable Class
def test_get_attribute_names(sheet_name='Data_Table_021311_1.xml'): "Tests the get_attribute_name method of the DataTable Class" os.chdir(TESTS_DIRECTORY) measurement=DataTable(sheet_name) names=measurement.get_attribute_names() print 'the names list is:',names print 'Using the names list to create a data table:' print '*'*80+'\n'+'%s %s %s'%(names[0], names[1], names[2])+'\n'+'*'*80 for index,item in enumerate(measurement.to_list(names[0])): row='' for name in names: row=measurement.to_list(name)[index] +'\t'+row print row
def test_get_header(
)
Test of the get header function of the DataTable Class
def test_get_header(): """ Test of the get header function of the DataTable Class """ test_dictionary={'Data_Description':{'x':'X Distance in microns.', 'y':'y Distance in microns.','Notes':'This data is fake'},'Data':[[1,2],[2,3]]} new_table=DataTable(**{'data_dictionary':test_dictionary}) header=new_table.get_header() print header print new_table.get_header('xml')
def test_log_addition(
)
Script to develop test the add attribute for the class XMLLog
def test_log_addition(): """ Script to develop test the __add__ attribute for the class XMLLog""" # First we want to know how a copy works os.chdir(TESTS_DIRECTORY) import time log_1=XMLLog() log_1.add_entry("I am Log Number One") time.sleep(.3) log_2=XMLLog() log_2.add_entry("I am Log Number 2") print('Log_1 Contents: using print') print log_1 print('Log_2 Contents: using print') print log_2 print('Log_1+Log_2 Contents: using print') print log_1+log_2
def test_open_measurement(
sheet_name='Data_Table_021311_1.xml')
Tests opening a sheet
def test_open_measurement(sheet_name='Data_Table_021311_1.xml'): """Tests opening a sheet""" os.chdir(TESTS_DIRECTORY) measurement=DataTable(sheet_name) print("The file path is {0}".format(measurement.path)) #print measurement print measurement.get_header()
def test_show(
)
Tests the show() method of the XMLLog class
def test_show(): "Tests the show() method of the XMLLog class" os.chdir(TESTS_DIRECTORY) new_log=XMLLog() print 'New Log Created...' print 'The Result of Show() is:' print '*'*80 entries=['1','2','Now I see!', 'Today was a good day'] for entry in entries: new_log.add_entry(entry) print new_log.show() print '\n'*4 print 'The Result of XMLLog.show(xml) is:' print '*'*80 print new_log.show('xml') #the window version new_log.show('wx')
def test_to_HTML(
)
Tests the to_HTML method of the XMLLog class
def test_to_HTML(): "Tests the to_HTML method of the XMLLog class" os.chdir(TESTS_DIRECTORY) new_log=XMLLog() print 'New Log Created...' print 'The Result of Show() is:' print '*'*80 entries=['1','2','Now I see!', 'Today was a good day'] for entry in entries: new_log.add_entry(entry) print new_log.show() print '\n'*4 print 'The Result of XMLLog.to_HTML(xml) is:' print '*'*80 print new_log.to_HTML()
Classes
class ChangeXMLLog
A XMLLog for storing changes to a program
class ChangeXMLLog(XMLLog): """ A XMLLog for storing changes to a program""" def __init__(self,path=None,program_name=None): XMLLog.__init__(self,path) # set the description element if it is a new log if path is None: self.add_ChangeXMLLog_description(program_name) def add_ChangeXMLLog_description(self,program_name=None): """ Adds a description of the change log as element Index=-1""" if program_name is None: program_name='a program' description="""This is a change log for %s. It consists of entries with a date attribute, an Index attribute that is a simple integer, and text describing the changes made to %s."""%(program_name,program_name) self.add_description(description)
Ancestors (in MRO)
Instance variables
Methods
def __init__(
self, path=None, program_name=None)
Intializes the XMLLog
def __init__(self,path=None,program_name=None): XMLLog.__init__(self,path) # set the description element if it is a new log if path is None: self.add_ChangeXMLLog_description(program_name)
def add_ChangeXMLLog_description(
self, program_name=None)
Adds a description of the change log as element Index=-1
def add_ChangeXMLLog_description(self,program_name=None): """ Adds a description of the change log as element Index=-1""" if program_name is None: program_name='a program' description="""This is a change log for %s. It consists of entries with a date attribute, an Index attribute that is a simple integer, and text describing the changes made to %s."""%(program_name,program_name) self.add_description(description)
def add_description(
self, description=None)
Inheritance:
XMLLog
.add_description
Adds an entry with Index='-1' which holds data about the log itself
def add_description(self,description=None): """ Adds an entry with Index='-1' which holds data about the log itself""" root=self.document.documentElement new_entry=self.document.createElement('Entry') if not description is None: text_node=self.document.createTextNode(description) new_entry.appendChild(text_node) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(-1)) # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary()
def add_entry(
self, entry=None)
Adds an entry element to the current log
def add_entry(self,entry=None): """ Adds an entry element to the current log""" root=self.document.documentElement if entry is None: new_entry=self.document.createElement('Entry') value='' elif type(entry) is str: if re.search('<Entry>(.)+</Entry>',entry): new_document=xml.dom.minidom.parseString(new_entry) new_entry=new_document.documentElement else: new_document=xml.dom.minidom.parseString('<Entry>' +entry+'</Entry>') new_entry=new_document.documentElement else: new_entry=entry # Find the max of Index's and add 1 to make a new Index if len(self.Index_node_dictionary)==0: new_Index='1' else: max_Index=max([int(Index) for Index in self.Index_node_dictionary.keys()]) new_Index=str(max_Index+1) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(new_Index)) if new_entry.getAttribute('Date'): pass else: # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() try: value=new_entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':new_entry.getAttribute('Index'), 'Date':new_entry.getAttribute('Date')}
def current_entry_to_HTML(
self, XSLT=None)
Inheritance:
XMLLog
.current_entry_to_HTML
Returns HTML string by applying a XSL to the XML document
def current_entry_to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: XSLT=self.options['entry_style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) current_entry_XML=self.Index_node_dictionary[self.current_entry['Index']] HTML=XSL_transform(etree.XML(current_entry_XML.toxml())) return HTML
def edit_entry(
self, old_Index, new_value=None, new_Index=None, new_Date=None)
Inheritance:
XMLLog
.edit_entry
Edits and existing entry by replacing the existing values with new ones
def edit_entry(self,old_Index,new_value=None,new_Index=None,new_Date=None): """Edits and existing entry by replacing the existing values with new ones""" node=self.get_entry(str(old_Index)) if not new_value is None: new_text_node=self.document.createTextNode(new_value) try: old_text_node=node.childNodes[0] node.removeChild(old_text_node) except: pass node.appendChild(new_text_node) elif not new_Index is None: node.setAttribute('Index',new_Index) elif not new_Date is None: node.setAttribute('Date',new_Date) self.current_entry={'Tag':'Entry','Value':node.childNodes[0].data,'Index':node.getAttribute('Index'), 'Date':node.getAttribute('Date')}
def get_entry(
self, Index)
Returns the entry selcted by Index
def get_entry(self,Index): """ Returns the entry selcted by Index""" return self.Index_node_dictionary[str(Index)]
def next_entry(
self)
Inheritance:
XMLLog
.next_entry
Sets current entry to the one after
def next_entry(self): """Sets current entry to the one after""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index+1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if max(Indices)>Index: Indices.sort() new_Index=Indices[Indices.index(Index)+1] else: Indices.remove(Index) new_Index=min(Indices) self.set_current_entry(new_Index)
def previous_entry(
self)
Inheritance:
XMLLog
.previous_entry
Sets current entry to the one before
def previous_entry(self): """Sets current entry to the one before""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index-1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if min(Indices)<Index: Indices.sort() new_Index=Indices[Indices.index(Index)-1] else: Indices.remove(Index) if len(Indices)>0: new_Index=max(Indices) else: new_Index=Index self.set_current_entry(new_Index)
def remove_entry(
self, Index)
Inheritance:
XMLLog
.remove_entry
Removes the entry using the Index attribute
def remove_entry(self,Index): """ Removes the entry using the Index attribute""" root=self.document.documentElement root.removeChild(self.Index_node_dictionary[Index]) self.update_Index_node_dictionary()
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def set_current_entry(
self, Index=-1)
Inheritance:
XMLLog
.set_current_entry
Sets self.current_entry
def set_current_entry(self,Index=-1): """Sets self.current_entry """ entry=self.Index_node_dictionary[str(Index)] try: value=entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':entry.getAttribute('Index'), 'Date':entry.getAttribute('Date')}
def show(
self, mode='text')
Displays a XMLLog either as formatted text in the command line or in a window (using wx)
def show(self,mode='text'): """ Displays a XMLLog either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML)
def update_Index_node_dictionary(
self)
Inheritance:
XMLLog
.update_Index_node_dictionary
Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document
def update_Index_node_dictionary(self): """ Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document""" self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')])
class DataTable
This is a XML data table class with an optional description
class DataTable(XMLBase): """ This is a XML data table class with an optional description""" def __init__(self,file_path=None,**options): """ Intializes the DataTable Class. Passing **{'data_table':[mylist]} creates a table with x1 and x2 as column names. Passing **{'data_dictionary':{'Data_Description':{'Tag':'Text',etc}, 'Data':[{'x':1,'y':2},{'x':2,'y':3}] """ # the general idea is <Data_Description/><Data><Tuple i=''/></Data> # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"Data_Table", "style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_MEASUREMENT_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Data', "general_descriptor":'Table', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) try: data_table=self.options['data_table'] if len(data_table)>0: data_node=self.list_to_XML(data_table) self.document.documentElement.appendChild(data_node) except: pass try: data_dictionary=self.options['data_dictionary'] if len(data_dictionary)>0: for key,value in data_dictionary.iteritems(): # This hanldes Tag:Text dictionaries if re.search('description',key,re.IGNORECASE): #This is the flat dictionary handling code {"Data_Description:{key:value}} #Need one that is {"Data_Description":{"Context":{key:value}}} new_entry=self.document.createElement(key) for tag,element_text in value.iteritems(): if type(element_text) is DictionaryType: new_tag=self.document.createElement(tag) new_entry.appendChild(new_tag) for inner_tag,inner_element_text in element_text.iteritems(): new_inner_tag=self.document.createElement(inner_tag) new_inner_text=self.document.createTextNode(inner_element_text) new_inner_tag.appendChild(new_inner_text) new_tag.appendChild(new_inner_tag) else: new_tag=self.document.createElement(tag) new_text=self.document.createTextNode(element_text) new_tag.appendChild(new_text) new_entry.appendChild(new_tag) self.document.documentElement.appendChild(new_entry) if re.search('data',key,re.IGNORECASE) and not re.search('Description',key,re.IGNORECASE): new_entry=self.list_to_XML(value) self.document.documentElement.appendChild(new_entry) except:pass def list_to_XML(self,data_list): """ Converts a list to XML document""" data_node=self.document.createElement('Data') #self.document.documentElement.appendChild(data_node) for row in data_list: if type(row) in [ListType,TupleType]: new_entry=self.document.createElement('Tuple') for j,datum in enumerate(row): x_attribute=self.document.createAttribute('X%s'%j) new_entry.setAttributeNode(x_attribute) new_entry.setAttribute('X%s'%j,str(datum)) data_node.appendChild(new_entry) elif type(row) is DictionaryType: new_entry=self.document.createElement('Tuple') for key,datum in row.iteritems(): x_attribute=self.document.createAttribute(key) new_entry.setAttributeNode(x_attribute) new_entry.setAttribute(key,str(datum)) data_node.appendChild(new_entry) return data_node def get_attribute_names(self): """ Returns the attribute names in the first tuple element in the 'data' element """ attribute_names=[] data_nodes=self.document.getElementsByTagName('Data') first_tuple_node=data_nodes[0].childNodes[1] text=first_tuple_node.toprettyxml() text_list=text.split(' ') #print text_list for item in text_list: try: match=re.search('(?P<attribute_name>\w+)=',item) name=match.group('attribute_name') #print name attribute_names.append(name) except:pass return attribute_names def to_list(self,attribute_name): """ Outputs the data as a list given a data column (attribute) name""" try: node_list=self.document.getElementsByTagName('Tuple') data_list=[node.getAttribute(attribute_name) for node in node_list] return data_list except: return None def to_tuple_list(self,attribute_names): """ Returns a list of tuples for the specified list of attribute names""" try: node_list=self.document.getElementsByTagName('Tuple') data_list=[tuple([node.getAttribute(attribute_name) for attribute_name in attribute_names]) for node in node_list] return data_list except: return None def get_header(self,style='txt'): """ Creates a header from the data description if there is one""" try: node_list=self.document.getElementsByTagName('Data_Description') data_description=node_list[0] out='' if style in ['txt','text','ascii']: for child in data_description.childNodes: try: out=out+'%s: %s'%(child.nodeName,child.firstChild.nodeValue)+'\n' except:pass return out elif re.search('xml',style,flags=re.IGNORECASE): out=data_description.toprettyxml() return out except: raise
Ancestors (in MRO)
Instance variables
Methods
def __init__(
self, file_path=None, **options)
Intializes the DataTable Class. Passing {'data_table':[mylist]} creates a table with x1 and x2 as column names. Passing {'data_dictionary':{'Data_Description':{'Tag':'Text',etc}, 'Data':[{'x':1,'y':2},{'x':2,'y':3}]
def __init__(self,file_path=None,**options): """ Intializes the DataTable Class. Passing **{'data_table':[mylist]} creates a table with x1 and x2 as column names. Passing **{'data_dictionary':{'Data_Description':{'Tag':'Text',etc}, 'Data':[{'x':1,'y':2},{'x':2,'y':3}] """ # the general idea is <Data_Description/><Data><Tuple i=''/></Data> # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"Data_Table", "style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_MEASUREMENT_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Data', "general_descriptor":'Table', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) try: data_table=self.options['data_table'] if len(data_table)>0: data_node=self.list_to_XML(data_table) self.document.documentElement.appendChild(data_node) except: pass try: data_dictionary=self.options['data_dictionary'] if len(data_dictionary)>0: for key,value in data_dictionary.iteritems(): # This hanldes Tag:Text dictionaries if re.search('description',key,re.IGNORECASE): #This is the flat dictionary handling code {"Data_Description:{key:value}} #Need one that is {"Data_Description":{"Context":{key:value}}} new_entry=self.document.createElement(key) for tag,element_text in value.iteritems(): if type(element_text) is DictionaryType: new_tag=self.document.createElement(tag) new_entry.appendChild(new_tag) for inner_tag,inner_element_text in element_text.iteritems(): new_inner_tag=self.document.createElement(inner_tag) new_inner_text=self.document.createTextNode(inner_element_text) new_inner_tag.appendChild(new_inner_text) new_tag.appendChild(new_inner_tag) else: new_tag=self.document.createElement(tag) new_text=self.document.createTextNode(element_text) new_tag.appendChild(new_text) new_entry.appendChild(new_tag) self.document.documentElement.appendChild(new_entry) if re.search('data',key,re.IGNORECASE) and not re.search('Description',key,re.IGNORECASE): new_entry=self.list_to_XML(value) self.document.documentElement.appendChild(new_entry) except:pass
def get_attribute_names(
self)
Returns the attribute names in the first tuple element in the 'data' element
def get_attribute_names(self): """ Returns the attribute names in the first tuple element in the 'data' element """ attribute_names=[] data_nodes=self.document.getElementsByTagName('Data') first_tuple_node=data_nodes[0].childNodes[1] text=first_tuple_node.toprettyxml() text_list=text.split(' ') #print text_list for item in text_list: try: match=re.search('(?P<attribute_name>\w+)=',item) name=match.group('attribute_name') #print name attribute_names.append(name) except:pass return attribute_names
def get_header(
self, style='txt')
Creates a header from the data description if there is one
def get_header(self,style='txt'): """ Creates a header from the data description if there is one""" try: node_list=self.document.getElementsByTagName('Data_Description') data_description=node_list[0] out='' if style in ['txt','text','ascii']: for child in data_description.childNodes: try: out=out+'%s: %s'%(child.nodeName,child.firstChild.nodeValue)+'\n' except:pass return out elif re.search('xml',style,flags=re.IGNORECASE): out=data_description.toprettyxml() return out except: raise
def list_to_XML(
self, data_list)
Converts a list to XML document
def list_to_XML(self,data_list): """ Converts a list to XML document""" data_node=self.document.createElement('Data') #self.document.documentElement.appendChild(data_node) for row in data_list: if type(row) in [ListType,TupleType]: new_entry=self.document.createElement('Tuple') for j,datum in enumerate(row): x_attribute=self.document.createAttribute('X%s'%j) new_entry.setAttributeNode(x_attribute) new_entry.setAttribute('X%s'%j,str(datum)) data_node.appendChild(new_entry) elif type(row) is DictionaryType: new_entry=self.document.createElement('Tuple') for key,datum in row.iteritems(): x_attribute=self.document.createAttribute(key) new_entry.setAttributeNode(x_attribute) new_entry.setAttribute(key,str(datum)) data_node.appendChild(new_entry) return data_node
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Inheritance:
XMLBase
.save_HTML
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def show(
self, mode='Window')
Displays a XML Document either as formatted text in the command line or in a window (using wx)
def show(self,mode='Window'): """ Displays a XML Document either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML)
def to_list(
self, attribute_name)
Outputs the data as a list given a data column (attribute) name
def to_list(self,attribute_name): """ Outputs the data as a list given a data column (attribute) name""" try: node_list=self.document.getElementsByTagName('Tuple') data_list=[node.getAttribute(attribute_name) for node in node_list] return data_list except: return None
def to_tuple_list(
self, attribute_names)
Returns a list of tuples for the specified list of attribute names
def to_tuple_list(self,attribute_names): """ Returns a list of tuples for the specified list of attribute names""" try: node_list=self.document.getElementsByTagName('Tuple') data_list=[tuple([node.getAttribute(attribute_name) for attribute_name in attribute_names]) for node in node_list] return data_list except: return None
class EndOfDayXMLLog
A XMLLog for storing notes about daily activities
class EndOfDayXMLLog(XMLLog): """ A XMLLog for storing notes about daily activities""" def __init__(self,path=None): options={"style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_STYLE.xsl').replace('\\','/')} XMLLog.__init__(self,path,**options) if path is None: self.add_EndOfDayXMLLog_description() self.information_tags=['Actions','Who_Did','Who_Suggested','Why','Conclusion','Data_Location'] def add_entry_information(self,Index=None,**entry): """ Adds a log specific entry takes a dicitionary in the form {'tag':value,..} this does not add atributes""" if Index is None: self.add_entry() Index=self.current_entry['Index'] try: node=self.get_entry(Index) except: raise for tag,value in entry.iteritems(): new_element=self.document.createElement(tag) new_text=self.document.createTextNode(str(value)) new_element.appendChild(new_text) node.appendChild(new_element) def add_EndOfDayXMLLog_description(self,program_name=None): """ Adds a description of the log as element Index=-1""" description="""This is a End of day log. It consists of entries with a date attribute, an Index attribute that is a simple integer, and xml tags describing daily activities""" self.add_description(description)
Ancestors (in MRO)
Instance variables
Methods
def __init__(
self, path=None)
Intializes the XMLLog
def __init__(self,path=None): options={"style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_STYLE.xsl').replace('\\','/')} XMLLog.__init__(self,path,**options) if path is None: self.add_EndOfDayXMLLog_description() self.information_tags=['Actions','Who_Did','Who_Suggested','Why','Conclusion','Data_Location']
def add_EndOfDayXMLLog_description(
self, program_name=None)
Adds a description of the log as element Index=-1
def add_EndOfDayXMLLog_description(self,program_name=None): """ Adds a description of the log as element Index=-1""" description="""This is a End of day log. It consists of entries with a date attribute, an Index attribute that is a simple integer, and xml tags describing daily activities""" self.add_description(description)
def add_description(
self, description=None)
Inheritance:
XMLLog
.add_description
Adds an entry with Index='-1' which holds data about the log itself
def add_description(self,description=None): """ Adds an entry with Index='-1' which holds data about the log itself""" root=self.document.documentElement new_entry=self.document.createElement('Entry') if not description is None: text_node=self.document.createTextNode(description) new_entry.appendChild(text_node) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(-1)) # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary()
def add_entry(
self, entry=None)
Adds an entry element to the current log
def add_entry(self,entry=None): """ Adds an entry element to the current log""" root=self.document.documentElement if entry is None: new_entry=self.document.createElement('Entry') value='' elif type(entry) is str: if re.search('<Entry>(.)+</Entry>',entry): new_document=xml.dom.minidom.parseString(new_entry) new_entry=new_document.documentElement else: new_document=xml.dom.minidom.parseString('<Entry>' +entry+'</Entry>') new_entry=new_document.documentElement else: new_entry=entry # Find the max of Index's and add 1 to make a new Index if len(self.Index_node_dictionary)==0: new_Index='1' else: max_Index=max([int(Index) for Index in self.Index_node_dictionary.keys()]) new_Index=str(max_Index+1) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(new_Index)) if new_entry.getAttribute('Date'): pass else: # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() try: value=new_entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':new_entry.getAttribute('Index'), 'Date':new_entry.getAttribute('Date')}
def add_entry_information(
self, Index=None, **entry)
Adds a log specific entry takes a dicitionary in the form {'tag':value,..} this does not add atributes
def add_entry_information(self,Index=None,**entry): """ Adds a log specific entry takes a dicitionary in the form {'tag':value,..} this does not add atributes""" if Index is None: self.add_entry() Index=self.current_entry['Index'] try: node=self.get_entry(Index) except: raise for tag,value in entry.iteritems(): new_element=self.document.createElement(tag) new_text=self.document.createTextNode(str(value)) new_element.appendChild(new_text) node.appendChild(new_element)
def current_entry_to_HTML(
self, XSLT=None)
Inheritance:
XMLLog
.current_entry_to_HTML
Returns HTML string by applying a XSL to the XML document
def current_entry_to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: XSLT=self.options['entry_style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) current_entry_XML=self.Index_node_dictionary[self.current_entry['Index']] HTML=XSL_transform(etree.XML(current_entry_XML.toxml())) return HTML
def edit_entry(
self, old_Index, new_value=None, new_Index=None, new_Date=None)
Inheritance:
XMLLog
.edit_entry
Edits and existing entry by replacing the existing values with new ones
def edit_entry(self,old_Index,new_value=None,new_Index=None,new_Date=None): """Edits and existing entry by replacing the existing values with new ones""" node=self.get_entry(str(old_Index)) if not new_value is None: new_text_node=self.document.createTextNode(new_value) try: old_text_node=node.childNodes[0] node.removeChild(old_text_node) except: pass node.appendChild(new_text_node) elif not new_Index is None: node.setAttribute('Index',new_Index) elif not new_Date is None: node.setAttribute('Date',new_Date) self.current_entry={'Tag':'Entry','Value':node.childNodes[0].data,'Index':node.getAttribute('Index'), 'Date':node.getAttribute('Date')}
def get_entry(
self, Index)
Returns the entry selcted by Index
def get_entry(self,Index): """ Returns the entry selcted by Index""" return self.Index_node_dictionary[str(Index)]
def next_entry(
self)
Inheritance:
XMLLog
.next_entry
Sets current entry to the one after
def next_entry(self): """Sets current entry to the one after""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index+1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if max(Indices)>Index: Indices.sort() new_Index=Indices[Indices.index(Index)+1] else: Indices.remove(Index) new_Index=min(Indices) self.set_current_entry(new_Index)
def previous_entry(
self)
Inheritance:
XMLLog
.previous_entry
Sets current entry to the one before
def previous_entry(self): """Sets current entry to the one before""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index-1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if min(Indices)<Index: Indices.sort() new_Index=Indices[Indices.index(Index)-1] else: Indices.remove(Index) if len(Indices)>0: new_Index=max(Indices) else: new_Index=Index self.set_current_entry(new_Index)
def remove_entry(
self, Index)
Inheritance:
XMLLog
.remove_entry
Removes the entry using the Index attribute
def remove_entry(self,Index): """ Removes the entry using the Index attribute""" root=self.document.documentElement root.removeChild(self.Index_node_dictionary[Index]) self.update_Index_node_dictionary()
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def set_current_entry(
self, Index=-1)
Inheritance:
XMLLog
.set_current_entry
Sets self.current_entry
def set_current_entry(self,Index=-1): """Sets self.current_entry """ entry=self.Index_node_dictionary[str(Index)] try: value=entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':entry.getAttribute('Index'), 'Date':entry.getAttribute('Date')}
def show(
self, mode='text')
Displays a XMLLog either as formatted text in the command line or in a window (using wx)
def show(self,mode='text'): """ Displays a XMLLog either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML)
def update_Index_node_dictionary(
self)
Inheritance:
XMLLog
.update_Index_node_dictionary
Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document
def update_Index_node_dictionary(self): """ Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document""" self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')])
class ErrorXMLLog
A XMLLog for storring errors generated by a program
class ErrorXMLLog(XMLLog): """ A XMLLog for storring errors generated by a program """ def __init__(self,path=None): XMLLog.__init__(self,path)
Ancestors (in MRO)
Instance variables
Methods
def __init__(
self, path=None)
Intializes the XMLLog
def __init__(self,path=None): XMLLog.__init__(self,path)
def add_description(
self, description=None)
Inheritance:
XMLLog
.add_description
Adds an entry with Index='-1' which holds data about the log itself
def add_description(self,description=None): """ Adds an entry with Index='-1' which holds data about the log itself""" root=self.document.documentElement new_entry=self.document.createElement('Entry') if not description is None: text_node=self.document.createTextNode(description) new_entry.appendChild(text_node) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(-1)) # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary()
def add_entry(
self, entry=None)
Adds an entry element to the current log
def add_entry(self,entry=None): """ Adds an entry element to the current log""" root=self.document.documentElement if entry is None: new_entry=self.document.createElement('Entry') value='' elif type(entry) is str: if re.search('<Entry>(.)+</Entry>',entry): new_document=xml.dom.minidom.parseString(new_entry) new_entry=new_document.documentElement else: new_document=xml.dom.minidom.parseString('<Entry>' +entry+'</Entry>') new_entry=new_document.documentElement else: new_entry=entry # Find the max of Index's and add 1 to make a new Index if len(self.Index_node_dictionary)==0: new_Index='1' else: max_Index=max([int(Index) for Index in self.Index_node_dictionary.keys()]) new_Index=str(max_Index+1) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(new_Index)) if new_entry.getAttribute('Date'): pass else: # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() try: value=new_entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':new_entry.getAttribute('Index'), 'Date':new_entry.getAttribute('Date')}
def current_entry_to_HTML(
self, XSLT=None)
Inheritance:
XMLLog
.current_entry_to_HTML
Returns HTML string by applying a XSL to the XML document
def current_entry_to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: XSLT=self.options['entry_style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) current_entry_XML=self.Index_node_dictionary[self.current_entry['Index']] HTML=XSL_transform(etree.XML(current_entry_XML.toxml())) return HTML
def edit_entry(
self, old_Index, new_value=None, new_Index=None, new_Date=None)
Inheritance:
XMLLog
.edit_entry
Edits and existing entry by replacing the existing values with new ones
def edit_entry(self,old_Index,new_value=None,new_Index=None,new_Date=None): """Edits and existing entry by replacing the existing values with new ones""" node=self.get_entry(str(old_Index)) if not new_value is None: new_text_node=self.document.createTextNode(new_value) try: old_text_node=node.childNodes[0] node.removeChild(old_text_node) except: pass node.appendChild(new_text_node) elif not new_Index is None: node.setAttribute('Index',new_Index) elif not new_Date is None: node.setAttribute('Date',new_Date) self.current_entry={'Tag':'Entry','Value':node.childNodes[0].data,'Index':node.getAttribute('Index'), 'Date':node.getAttribute('Date')}
def get_entry(
self, Index)
Returns the entry selcted by Index
def get_entry(self,Index): """ Returns the entry selcted by Index""" return self.Index_node_dictionary[str(Index)]
def next_entry(
self)
Inheritance:
XMLLog
.next_entry
Sets current entry to the one after
def next_entry(self): """Sets current entry to the one after""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index+1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if max(Indices)>Index: Indices.sort() new_Index=Indices[Indices.index(Index)+1] else: Indices.remove(Index) new_Index=min(Indices) self.set_current_entry(new_Index)
def previous_entry(
self)
Inheritance:
XMLLog
.previous_entry
Sets current entry to the one before
def previous_entry(self): """Sets current entry to the one before""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index-1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if min(Indices)<Index: Indices.sort() new_Index=Indices[Indices.index(Index)-1] else: Indices.remove(Index) if len(Indices)>0: new_Index=max(Indices) else: new_Index=Index self.set_current_entry(new_Index)
def remove_entry(
self, Index)
Inheritance:
XMLLog
.remove_entry
Removes the entry using the Index attribute
def remove_entry(self,Index): """ Removes the entry using the Index attribute""" root=self.document.documentElement root.removeChild(self.Index_node_dictionary[Index]) self.update_Index_node_dictionary()
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def set_current_entry(
self, Index=-1)
Inheritance:
XMLLog
.set_current_entry
Sets self.current_entry
def set_current_entry(self,Index=-1): """Sets self.current_entry """ entry=self.Index_node_dictionary[str(Index)] try: value=entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':entry.getAttribute('Index'), 'Date':entry.getAttribute('Date')}
def show(
self, mode='text')
Displays a XMLLog either as formatted text in the command line or in a window (using wx)
def show(self,mode='text'): """ Displays a XMLLog either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML)
def update_Index_node_dictionary(
self)
Inheritance:
XMLLog
.update_Index_node_dictionary
Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document
def update_Index_node_dictionary(self): """ Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document""" self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')])
class FileRegister
The base class for arbitrary database, which processes the File Register XML File.
class FileRegister(XMLBase): """ The base class for arbitrary database, which processes the File Register XML File.""" def __init__(self,file_path=None,**options): """ Initializes the File Register Class.""" # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"File_Registry", "style_sheet":os.path.join(XSLT_REPOSITORY,'FR_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Resource', "general_descriptor":'Registry', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')]) def create_Id(self,URL): """ Creates or returns the existing Id element of a URL""" parsed_URL=urlparse.urlparse(condition_URL(URL)) try: # Look in self.Id_dictionary, if it is not there catch # the exception KeyError and generate an Id. return self.Id_dictionary[URL.replace('///','')] except KeyError: # The Id is not in the existing list so start buliding Id. # Determine the IP Address of the host in the URL if parsed_URL[1] in ['',u'']: #if it is empty assume local host IP_address=socket.gethostbyaddr(socket.gethostname())[2][0] else: IP_address= socket.gethostbyaddr(parsed_URL[1])[2][0] Id_cache={} # We begin with all the entries with the same IP address for (key,value) in self.Id_dictionary.iteritems(): if value.startswith(IP_address): Id_cache[key]=value # If the Id_cache is empty then we just assign the number temp_Id=IP_address path_list=parsed_URL[2].split('/') file_extension=path_list[-1].split('.')[-1] if len(Id_cache) is 0: for index,part in enumerate(path_list): if index<len(path_list)-1: temp_Id=temp_Id+'.'+'11' elif index==len(path_list)-1: if (file_extension in DRIVER_FILE_EXTENSIONS): temp_Id=temp_Id+'.'+'31' elif os.path.isdir(parsed_URL[2]): temp_Id=temp_Id+'.'+'11' else: temp_Id=temp_Id+'.'+'21' return temp_Id # if it is not empty we have to a little work # remove the information about IP address place=0 #print path_list while place<=len(path_list): # If the Id_cache is empty assign the rest of the Id. if len(Id_cache) is 0: for index,part in enumerate(path_list[place:]): if index<len(path_list[place:])-1: temp_Id=temp_Id+'.'+'11' elif index==len(path_list[place:])-1: if (file_extension in DRIVER_FILE_EXTENSIONS): temp_Id=temp_Id+'.'+'31' elif os.path.isdir(parsed_URL[2]): temp_Id=temp_Id+'.'+'11' else: temp_Id=temp_Id+'.'+'21' return temp_Id # If the Id_cache is not empty else: path_cache=dict([(URL,URL_to_path(URL,form='list')) for URL in Id_cache.keys()]) print Id_cache part_cache=dict([(URL,[path_cache[URL][place], Id_cache[URL].split('.')[place+4]]) for URL in Id_cache.keys()]) parts_list=[part_cache[URL][0]for URL in Id_cache.keys()] node_number=max([int(Id_cache[URL].split('.')[place+4][1:]) for URL in Id_cache.keys()]) # If it is the last place if place==len(path_list)-1: new_node_number=node_number+1 if (file_extension in DRIVER_FILE_EXTENSIONS): new_node_type='3' elif os.path.isdir(parsed_URL[2]): new_node_type='1' else: new_node_type='2' temp_Id=temp_Id+'.'+new_node_type+str(new_node_number) return temp_Id # If it is not the last place assume it is a directory else: new_node_type='1' # Check to see if it is already in the FR if path_list[place] in parts_list: for URL in Id_cache.keys(): if part_cache[URL][0]==path_list[place]: new_node=part_cache[URL][1] # If not add one to node else: new_node_number=node_number+1 new_node=new_node_type+str(new_node_number) temp_Id=temp_Id+'.'+new_node # Update the Id_cache for the next round, and the place for URL in Id_cache.keys(): try: if not part_cache[URL][0]==path_list[place]: del(Id_cache[URL]) Id_cache[URL].split('.')[place+5] except KeyError: pass except IndexError: #print Id_cache,URL del(Id_cache[URL]) place=place+1 def add_entry(self,URL): """ Adds an entry to the current File Register """ URL=condition_URL(URL) if URL in self.Id_dictionary.keys(): print 'Already there' return # the xml entry is <File Date="" Host="" Type="" Id="" URL=""/> File_Registry=self.document.documentElement new_entry=self.document.createElement('File') # Make all the new attributes attributes=['Id','Host','Date','URL','Type'] new_attributes=dict([(attribute, self.document.createAttribute(attribute)) for attribute in \ attributes]) # Add the new attributes to the new entry for attribute in attributes: new_entry.setAttributeNode(new_attributes[attribute]) # Now assign the values attribute_values={} attribute_values['URL']=URL attribute_values['Id']=self.create_Id(URL) attribute_values['Date']=datetime.datetime.utcnow().isoformat() type_code=attribute_values['Id'].split('.')[-1][0] if type_code in ['1',u'1']: attribute_values['Type']="Directory" elif type_code in ['2',u'2']: attribute_values['Type']="Ordinary" elif type_code in ['3',u'3']: attribute_values['Type']="Driver" else: attribute_values['Type']="Other" parsed_URL=urlparse.urlparse(condition_URL(URL)) if parsed_URL[1] in ['',u'']: #if it is empty assume local host attribute_values['Host']= socket.gethostbyaddr(socket.gethostname())[0] else: attribute_values['Host']= parsed_URL[1] # Now set them all in the actual attribute for (key,value) in attribute_values.iteritems(): new_entry.setAttribute(key,value) File_Registry.appendChild(new_entry) # Finally update the self.Id_dictionary # Added boolean switch to speed up adding a lot of entries self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')]) # TODO : Add an input filter that guesses at what you inputed def add_tree(self,root,**options): """ Adds a directory and all sub folders and sub directories, **options provides a way to {'ignore','.pyc|etc'} or {'only','.png|.bmp'}""" # Deal with the optional parameters, these tend to make life easier default_options={'ignore':None,'only':None,'print_ignored_files':True, 'directories_only':False,'files_only':False} tree_options=default_options for option,value in options.iteritems(): tree_options[option]=value #print tree_options #condition the URL root_URL=condition_URL(root) path=URL_to_path(root_URL) # now we add the files and directories that jive with the options try: for (home,directories,files) in os.walk(path): #print (home,directories,files) for directory in directories:# had to change this, used to be first element in list try: if tree_options['files_only']: if tree_options['print_ignored_files']: print "ignoring %s because it is not a file"%file raise if tree_options['ignore'] is not None and re.search(tree_options['ignore'],directory): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%directory raise elif tree_options['only'] is not None and not re.search(tree_options['only'],directory): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%directory raise else: self.add_entry(condition_URL(os.path.join(home,directory))) self.save() except:pass for file in files: # had to change this 12/2012, used to be Second element in list try: if tree_options['directories_only']: if tree_options['print_ignored_files']: print "ignoring %s because it is not a directory"%file raise if tree_options['ignore'] is not None and re.search(tree_options['ignore'],file): if tree_options['print_ignored_files']: print "ignoring %s because it matches the ignore option"%file raise elif tree_options['only'] is not None and not re.search(tree_options['only'],file): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%file raise else: #print (home,file) self.add_entry(condition_URL(os.path.join(home,file))) self.save() except:raise except: raise #After all the files are added update the Id_dictionary self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')]) def remove_entry(self,URL=None,Id=None): """ Removes an entry in the current File Register """ File_Registry=self.document.documentElement if not URL is None: URL=condition_URL(URL) URL_FileNode_dictionary=dict([(node.getAttribute('URL'), node) for node in self.document.getElementsByTagName('File')]) File_Registry.removeChild(URL_FileNode_dictionary[URL]) else: Id_FileNode_dictionary=dict([(node.getAttribute('Id'), node) for node in self.document.getElementsByTagName('File')]) File_Registry.removeChild(Id_FileNode_dictionary[Id]) # Finally update the self.Id_dictionary self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in \ self.document.getElementsByTagName('File')])
Ancestors (in MRO)
Instance variables
var Id_dictionary
Methods
def __init__(
self, file_path=None, **options)
Initializes the File Register Class.
def __init__(self,file_path=None,**options): """ Initializes the File Register Class.""" # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"File_Registry", "style_sheet":os.path.join(XSLT_REPOSITORY,'FR_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Resource', "general_descriptor":'Registry', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')])
def add_entry(
self, URL)
Adds an entry to the current File Register
def add_entry(self,URL): """ Adds an entry to the current File Register """ URL=condition_URL(URL) if URL in self.Id_dictionary.keys(): print 'Already there' return # the xml entry is <File Date="" Host="" Type="" Id="" URL=""/> File_Registry=self.document.documentElement new_entry=self.document.createElement('File') # Make all the new attributes attributes=['Id','Host','Date','URL','Type'] new_attributes=dict([(attribute, self.document.createAttribute(attribute)) for attribute in \ attributes]) # Add the new attributes to the new entry for attribute in attributes: new_entry.setAttributeNode(new_attributes[attribute]) # Now assign the values attribute_values={} attribute_values['URL']=URL attribute_values['Id']=self.create_Id(URL) attribute_values['Date']=datetime.datetime.utcnow().isoformat() type_code=attribute_values['Id'].split('.')[-1][0] if type_code in ['1',u'1']: attribute_values['Type']="Directory" elif type_code in ['2',u'2']: attribute_values['Type']="Ordinary" elif type_code in ['3',u'3']: attribute_values['Type']="Driver" else: attribute_values['Type']="Other" parsed_URL=urlparse.urlparse(condition_URL(URL)) if parsed_URL[1] in ['',u'']: #if it is empty assume local host attribute_values['Host']= socket.gethostbyaddr(socket.gethostname())[0] else: attribute_values['Host']= parsed_URL[1] # Now set them all in the actual attribute for (key,value) in attribute_values.iteritems(): new_entry.setAttribute(key,value) File_Registry.appendChild(new_entry) # Finally update the self.Id_dictionary # Added boolean switch to speed up adding a lot of entries self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')])
def add_tree(
self, root, **options)
Adds a directory and all sub folders and sub directories, **options provides a way to {'ignore','.pyc|etc'} or {'only','.png|.bmp'}
def add_tree(self,root,**options): """ Adds a directory and all sub folders and sub directories, **options provides a way to {'ignore','.pyc|etc'} or {'only','.png|.bmp'}""" # Deal with the optional parameters, these tend to make life easier default_options={'ignore':None,'only':None,'print_ignored_files':True, 'directories_only':False,'files_only':False} tree_options=default_options for option,value in options.iteritems(): tree_options[option]=value #print tree_options #condition the URL root_URL=condition_URL(root) path=URL_to_path(root_URL) # now we add the files and directories that jive with the options try: for (home,directories,files) in os.walk(path): #print (home,directories,files) for directory in directories:# had to change this, used to be first element in list try: if tree_options['files_only']: if tree_options['print_ignored_files']: print "ignoring %s because it is not a file"%file raise if tree_options['ignore'] is not None and re.search(tree_options['ignore'],directory): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%directory raise elif tree_options['only'] is not None and not re.search(tree_options['only'],directory): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%directory raise else: self.add_entry(condition_URL(os.path.join(home,directory))) self.save() except:pass for file in files: # had to change this 12/2012, used to be Second element in list try: if tree_options['directories_only']: if tree_options['print_ignored_files']: print "ignoring %s because it is not a directory"%file raise if tree_options['ignore'] is not None and re.search(tree_options['ignore'],file): if tree_options['print_ignored_files']: print "ignoring %s because it matches the ignore option"%file raise elif tree_options['only'] is not None and not re.search(tree_options['only'],file): if tree_options['print_ignored_files']: print "ignoring %s because it does not match the only option"%file raise else: #print (home,file) self.add_entry(condition_URL(os.path.join(home,file))) self.save() except:raise except: raise #After all the files are added update the Id_dictionary self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in self.document.getElementsByTagName('File')])
def create_Id(
self, URL)
Creates or returns the existing Id element of a URL
def create_Id(self,URL): """ Creates or returns the existing Id element of a URL""" parsed_URL=urlparse.urlparse(condition_URL(URL)) try: # Look in self.Id_dictionary, if it is not there catch # the exception KeyError and generate an Id. return self.Id_dictionary[URL.replace('///','')] except KeyError: # The Id is not in the existing list so start buliding Id. # Determine the IP Address of the host in the URL if parsed_URL[1] in ['',u'']: #if it is empty assume local host IP_address=socket.gethostbyaddr(socket.gethostname())[2][0] else: IP_address= socket.gethostbyaddr(parsed_URL[1])[2][0] Id_cache={} # We begin with all the entries with the same IP address for (key,value) in self.Id_dictionary.iteritems(): if value.startswith(IP_address): Id_cache[key]=value # If the Id_cache is empty then we just assign the number temp_Id=IP_address path_list=parsed_URL[2].split('/') file_extension=path_list[-1].split('.')[-1] if len(Id_cache) is 0: for index,part in enumerate(path_list): if index<len(path_list)-1: temp_Id=temp_Id+'.'+'11' elif index==len(path_list)-1: if (file_extension in DRIVER_FILE_EXTENSIONS): temp_Id=temp_Id+'.'+'31' elif os.path.isdir(parsed_URL[2]): temp_Id=temp_Id+'.'+'11' else: temp_Id=temp_Id+'.'+'21' return temp_Id # if it is not empty we have to a little work # remove the information about IP address place=0 #print path_list while place<=len(path_list): # If the Id_cache is empty assign the rest of the Id. if len(Id_cache) is 0: for index,part in enumerate(path_list[place:]): if index<len(path_list[place:])-1: temp_Id=temp_Id+'.'+'11' elif index==len(path_list[place:])-1: if (file_extension in DRIVER_FILE_EXTENSIONS): temp_Id=temp_Id+'.'+'31' elif os.path.isdir(parsed_URL[2]): temp_Id=temp_Id+'.'+'11' else: temp_Id=temp_Id+'.'+'21' return temp_Id # If the Id_cache is not empty else: path_cache=dict([(URL,URL_to_path(URL,form='list')) for URL in Id_cache.keys()]) print Id_cache part_cache=dict([(URL,[path_cache[URL][place], Id_cache[URL].split('.')[place+4]]) for URL in Id_cache.keys()]) parts_list=[part_cache[URL][0]for URL in Id_cache.keys()] node_number=max([int(Id_cache[URL].split('.')[place+4][1:]) for URL in Id_cache.keys()]) # If it is the last place if place==len(path_list)-1: new_node_number=node_number+1 if (file_extension in DRIVER_FILE_EXTENSIONS): new_node_type='3' elif os.path.isdir(parsed_URL[2]): new_node_type='1' else: new_node_type='2' temp_Id=temp_Id+'.'+new_node_type+str(new_node_number) return temp_Id # If it is not the last place assume it is a directory else: new_node_type='1' # Check to see if it is already in the FR if path_list[place] in parts_list: for URL in Id_cache.keys(): if part_cache[URL][0]==path_list[place]: new_node=part_cache[URL][1] # If not add one to node else: new_node_number=node_number+1 new_node=new_node_type+str(new_node_number) temp_Id=temp_Id+'.'+new_node # Update the Id_cache for the next round, and the place for URL in Id_cache.keys(): try: if not part_cache[URL][0]==path_list[place]: del(Id_cache[URL]) Id_cache[URL].split('.')[place+5] except KeyError: pass except IndexError: #print Id_cache,URL del(Id_cache[URL]) place=place+1
def remove_entry(
self, URL=None, Id=None)
Removes an entry in the current File Register
def remove_entry(self,URL=None,Id=None): """ Removes an entry in the current File Register """ File_Registry=self.document.documentElement if not URL is None: URL=condition_URL(URL) URL_FileNode_dictionary=dict([(node.getAttribute('URL'), node) for node in self.document.getElementsByTagName('File')]) File_Registry.removeChild(URL_FileNode_dictionary[URL]) else: Id_FileNode_dictionary=dict([(node.getAttribute('Id'), node) for node in self.document.getElementsByTagName('File')]) File_Registry.removeChild(Id_FileNode_dictionary[Id]) # Finally update the self.Id_dictionary self.Id_dictionary=dict([(str(node.getAttribute('URL')), str(node.getAttribute('Id'))) for node in \ self.document.getElementsByTagName('File')])
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Inheritance:
XMLBase
.save_HTML
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def show(
self, mode='Window')
Displays a XML Document either as formatted text in the command line or in a window (using wx)
def show(self,mode='Window'): """ Displays a XML Document either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML)
class Metadata
Metadata holds the metadata tags for a FileRegistry, If it already exists and the parser gives an error check the xml file for special characters like
class Metadata(XMLBase): """ Metadata holds the metadata tags for a FileRegistry, If it already exists and the parser gives an error check the xml file for special characters like """ def __init__(self,file_path=None,**options):#FileRegistry,Metadata_File=None) """ Intializes the class Metadata""" # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"Metadata_Registry", "style_sheet":os.path.join(XSLT_REPOSITORY,'METADATA_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Metadata', "general_descriptor":'Registry', "directory":None, "extension":'xml', "metadata_file":None } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value FileRegistry=file_path Metadata_File=self.options['metadata_file'] # Process the file register if type(FileRegistry) is InstanceType: self.FileRegister=FileRegistry elif type(FileRegistry) in StringTypes: self.FileRegister=FileRegister(FileRegistry) # Process or create the Metadata File if Metadata_File is None: # Make the metadata file based on the file register FileRegister_path=self.FileRegister.path.replace('\\','/') FileRegister_name=FileRegister_path.split('/')[-1] FileRegister_ext=FileRegister_name.split('.')[-1] Metadata_name=FileRegister_name.replace('.'+FileRegister_ext, '_Metadata.'+FileRegister_ext) self.path=FileRegister_path.replace(FileRegister_name,Metadata_name) self.document=self.FileRegister.document # delete old processing instructions for node in self.document.childNodes: if node.nodeType is 7: self.document.removeChild(node) node.unlink() # add in the default xsl new_node=self.document.createProcessingInstruction( 'xml-stylesheet', u'type="text/xsl" href="%s"'%self.options['style_sheet']) self.document.insertBefore(new_node,self.document.documentElement) # make sure there is a fileregister reference FR_Path=self.FileRegister.path new_node=self.document.createProcessingInstruction(\ 'xml-FileRegistry',\ 'href=\"%s\"'%(self.FileRegister.path)) self.document.insertBefore(new_node,self.document.documentElement) else: # The metadata file exists as a saved file or an instance if type(Metadata_File) is InstanceType: self.document=Metadata_File.document self.path=Metadata_File.path elif type(Metadata_File) in StringTypes: XMLBase.__init__(self,file_path,**self.options) # TODO: This dictionary of nodes worries me-- it may not scale well self.node_dictionary=dict([(str(node.getAttribute('URL')), node) for node in self.document.getElementsByTagName('File')]) self.URL_dictionary=dict([(str(node.getAttribute('Id')), str(node.getAttribute('URL'))) for node in self.document.getElementsByTagName('File')]) self.name_dictionary=dict([(Id,os.path.split(self.URL_dictionary[Id])[1]) for Id in self.URL_dictionary.keys()]) self.current_node=self.node_dictionary.values()[0] def search_name(self,name=None,re_flags=re.IGNORECASE): """ Returns a list of URL's that have an element matching name""" try: if re_flags in [None,'']: urls=filter(lambda x: re.search(name,x), self.URL_dictionary.values()) return urls else: urls=filter(lambda x: re.search(name,x,flags=re_flags), self.URL_dictionary.values()) return urls except: raise if XSLT_CAPABLE: def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return HTML def get_file_node(self,URL=None,Id=None): """ Returns the file node specified by URL or Id""" if not URL is None: URL=condition_URL(URL) self.current_node=self.node_dictionary[URL] return self.current_node elif not Id is None: self.current_node=self.node_dictionary[self.URL_dictionary[Id]] return self.current_node def set_current_node(self,URL=None,Id=None): """ Sets the current file node to the one specified by URL or Id""" if not URL is None: URL=condition_URL(URL) self.current_node=self.node_dictionary[URL] elif not Id is None: self.current_node=self.node_dictionary[self.URL_dictionary[Id]] def add_element_to_current_node(self,XML_tag=None,value=None,node=None,**Atributes): """Adds a metadata element to the current file node""" if node is None: new_element=self.document.createElement(XML_tag) else: new_element=node if not value is None: new_text=self.document.createTextNode(str(value)) new_element.appendChild(new_text) attributes=[key for key in Atributes.keys()] new_attributes=dict([(attribute, self.document.createAttribute(attribute)) for attribute in \ attributes]) for (key,value) in Atributes.iteritems(): new_element.setAttribute(key,str(value)) self.current_node.appendChild(new_element) def remove_element_in_current_node(self,element_name): """Removes all metadata elements with the same tagname in the current file node""" nodes_to_remove=self.current_node.getElementsByTagName(element_name) try: for node in nodes_to_remove: self.current_node.removeChild(node) except:pass if XSLT_CAPABLE: def current_node_to_HTML(self,XSLT=None): """Returns a HTML document from the current node""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.current_node.toxml())) return HTML def print_current_node(self): """ Prints the current node """ print self.current_node.toxml()
Ancestors (in MRO)
Instance variables
var URL_dictionary
var current_node
var name_dictionary
var node_dictionary
Methods
def __init__(
self, file_path=None, **options)
Intializes the class Metadata
def __init__(self,file_path=None,**options):#FileRegistry,Metadata_File=None) """ Intializes the class Metadata""" # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"Metadata_Registry", "style_sheet":os.path.join(XSLT_REPOSITORY,'METADATA_STYLE.xsl').replace('\\','/'), "specific_descriptor":'Metadata', "general_descriptor":'Registry', "directory":None, "extension":'xml', "metadata_file":None } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value FileRegistry=file_path Metadata_File=self.options['metadata_file'] # Process the file register if type(FileRegistry) is InstanceType: self.FileRegister=FileRegistry elif type(FileRegistry) in StringTypes: self.FileRegister=FileRegister(FileRegistry) # Process or create the Metadata File if Metadata_File is None: # Make the metadata file based on the file register FileRegister_path=self.FileRegister.path.replace('\\','/') FileRegister_name=FileRegister_path.split('/')[-1] FileRegister_ext=FileRegister_name.split('.')[-1] Metadata_name=FileRegister_name.replace('.'+FileRegister_ext, '_Metadata.'+FileRegister_ext) self.path=FileRegister_path.replace(FileRegister_name,Metadata_name) self.document=self.FileRegister.document # delete old processing instructions for node in self.document.childNodes: if node.nodeType is 7: self.document.removeChild(node) node.unlink() # add in the default xsl new_node=self.document.createProcessingInstruction( 'xml-stylesheet', u'type="text/xsl" href="%s"'%self.options['style_sheet']) self.document.insertBefore(new_node,self.document.documentElement) # make sure there is a fileregister reference FR_Path=self.FileRegister.path new_node=self.document.createProcessingInstruction(\ 'xml-FileRegistry',\ 'href=\"%s\"'%(self.FileRegister.path)) self.document.insertBefore(new_node,self.document.documentElement) else: # The metadata file exists as a saved file or an instance if type(Metadata_File) is InstanceType: self.document=Metadata_File.document self.path=Metadata_File.path elif type(Metadata_File) in StringTypes: XMLBase.__init__(self,file_path,**self.options) # TODO: This dictionary of nodes worries me-- it may not scale well self.node_dictionary=dict([(str(node.getAttribute('URL')), node) for node in self.document.getElementsByTagName('File')]) self.URL_dictionary=dict([(str(node.getAttribute('Id')), str(node.getAttribute('URL'))) for node in self.document.getElementsByTagName('File')]) self.name_dictionary=dict([(Id,os.path.split(self.URL_dictionary[Id])[1]) for Id in self.URL_dictionary.keys()]) self.current_node=self.node_dictionary.values()[0]
def add_element_to_current_node(
self, XML_tag=None, value=None, node=None, **Atributes)
Adds a metadata element to the current file node
def add_element_to_current_node(self,XML_tag=None,value=None,node=None,**Atributes): """Adds a metadata element to the current file node""" if node is None: new_element=self.document.createElement(XML_tag) else: new_element=node if not value is None: new_text=self.document.createTextNode(str(value)) new_element.appendChild(new_text) attributes=[key for key in Atributes.keys()] new_attributes=dict([(attribute, self.document.createAttribute(attribute)) for attribute in \ attributes]) for (key,value) in Atributes.iteritems(): new_element.setAttribute(key,str(value)) self.current_node.appendChild(new_element)
def current_node_to_HTML(
self, XSLT=None)
Returns a HTML document from the current node
def current_node_to_HTML(self,XSLT=None): """Returns a HTML document from the current node""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.current_node.toxml())) return HTML
def get_file_node(
self, URL=None, Id=None)
Returns the file node specified by URL or Id
def get_file_node(self,URL=None,Id=None): """ Returns the file node specified by URL or Id""" if not URL is None: URL=condition_URL(URL) self.current_node=self.node_dictionary[URL] return self.current_node elif not Id is None: self.current_node=self.node_dictionary[self.URL_dictionary[Id]] return self.current_node
def print_current_node(
self)
Prints the current node
def print_current_node(self): """ Prints the current node """ print self.current_node.toxml()
def remove_element_in_current_node(
self, element_name)
Removes all metadata elements with the same tagname in the current file node
def remove_element_in_current_node(self,element_name): """Removes all metadata elements with the same tagname in the current file node""" nodes_to_remove=self.current_node.getElementsByTagName(element_name) try: for node in nodes_to_remove: self.current_node.removeChild(node) except:pass
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Inheritance:
XMLBase
.save_HTML
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def search_name(
self, name=None, re_flags=2)
Returns a list of URL's that have an element matching name
def search_name(self,name=None,re_flags=re.IGNORECASE): """ Returns a list of URL's that have an element matching name""" try: if re_flags in [None,'']: urls=filter(lambda x: re.search(name,x), self.URL_dictionary.values()) return urls else: urls=filter(lambda x: re.search(name,x,flags=re_flags), self.URL_dictionary.values()) return urls except: raise
def set_current_node(
self, URL=None, Id=None)
Sets the current file node to the one specified by URL or Id
def set_current_node(self,URL=None,Id=None): """ Sets the current file node to the one specified by URL or Id""" if not URL is None: URL=condition_URL(URL) self.current_node=self.node_dictionary[URL] elif not Id is None: self.current_node=self.node_dictionary[self.URL_dictionary[Id]]
def show(
self, mode='Window')
Displays a XML Document either as formatted text in the command line or in a window (using wx)
def show(self,mode='Window'): """ Displays a XML Document either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return HTML
class ServiceXMLLog
A XMLLog for servicing an instrument or experiment
class ServiceXMLLog(XMLLog): """ A XMLLog for servicing an instrument or experiment """ def __init__(self,path=None,instrument_name=None): XMLLog.__init__(self,path)
Ancestors (in MRO)
Instance variables
Methods
def __init__(
self, path=None, instrument_name=None)
Intializes the XMLLog
def __init__(self,path=None,instrument_name=None): XMLLog.__init__(self,path)
def add_description(
self, description=None)
Inheritance:
XMLLog
.add_description
Adds an entry with Index='-1' which holds data about the log itself
def add_description(self,description=None): """ Adds an entry with Index='-1' which holds data about the log itself""" root=self.document.documentElement new_entry=self.document.createElement('Entry') if not description is None: text_node=self.document.createTextNode(description) new_entry.appendChild(text_node) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(-1)) # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary()
def add_entry(
self, entry=None)
Adds an entry element to the current log
def add_entry(self,entry=None): """ Adds an entry element to the current log""" root=self.document.documentElement if entry is None: new_entry=self.document.createElement('Entry') value='' elif type(entry) is str: if re.search('<Entry>(.)+</Entry>',entry): new_document=xml.dom.minidom.parseString(new_entry) new_entry=new_document.documentElement else: new_document=xml.dom.minidom.parseString('<Entry>' +entry+'</Entry>') new_entry=new_document.documentElement else: new_entry=entry # Find the max of Index's and add 1 to make a new Index if len(self.Index_node_dictionary)==0: new_Index='1' else: max_Index=max([int(Index) for Index in self.Index_node_dictionary.keys()]) new_Index=str(max_Index+1) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(new_Index)) if new_entry.getAttribute('Date'): pass else: # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() try: value=new_entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':new_entry.getAttribute('Index'), 'Date':new_entry.getAttribute('Date')}
def current_entry_to_HTML(
self, XSLT=None)
Inheritance:
XMLLog
.current_entry_to_HTML
Returns HTML string by applying a XSL to the XML document
def current_entry_to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: XSLT=self.options['entry_style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) current_entry_XML=self.Index_node_dictionary[self.current_entry['Index']] HTML=XSL_transform(etree.XML(current_entry_XML.toxml())) return HTML
def edit_entry(
self, old_Index, new_value=None, new_Index=None, new_Date=None)
Inheritance:
XMLLog
.edit_entry
Edits and existing entry by replacing the existing values with new ones
def edit_entry(self,old_Index,new_value=None,new_Index=None,new_Date=None): """Edits and existing entry by replacing the existing values with new ones""" node=self.get_entry(str(old_Index)) if not new_value is None: new_text_node=self.document.createTextNode(new_value) try: old_text_node=node.childNodes[0] node.removeChild(old_text_node) except: pass node.appendChild(new_text_node) elif not new_Index is None: node.setAttribute('Index',new_Index) elif not new_Date is None: node.setAttribute('Date',new_Date) self.current_entry={'Tag':'Entry','Value':node.childNodes[0].data,'Index':node.getAttribute('Index'), 'Date':node.getAttribute('Date')}
def get_entry(
self, Index)
Returns the entry selcted by Index
def get_entry(self,Index): """ Returns the entry selcted by Index""" return self.Index_node_dictionary[str(Index)]
def next_entry(
self)
Inheritance:
XMLLog
.next_entry
Sets current entry to the one after
def next_entry(self): """Sets current entry to the one after""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index+1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if max(Indices)>Index: Indices.sort() new_Index=Indices[Indices.index(Index)+1] else: Indices.remove(Index) new_Index=min(Indices) self.set_current_entry(new_Index)
def previous_entry(
self)
Inheritance:
XMLLog
.previous_entry
Sets current entry to the one before
def previous_entry(self): """Sets current entry to the one before""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index-1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if min(Indices)<Index: Indices.sort() new_Index=Indices[Indices.index(Index)-1] else: Indices.remove(Index) if len(Indices)>0: new_Index=max(Indices) else: new_Index=Index self.set_current_entry(new_Index)
def remove_entry(
self, Index)
Inheritance:
XMLLog
.remove_entry
Removes the entry using the Index attribute
def remove_entry(self,Index): """ Removes the entry using the Index attribute""" root=self.document.documentElement root.removeChild(self.Index_node_dictionary[Index]) self.update_Index_node_dictionary()
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def set_current_entry(
self, Index=-1)
Inheritance:
XMLLog
.set_current_entry
Sets self.current_entry
def set_current_entry(self,Index=-1): """Sets self.current_entry """ entry=self.Index_node_dictionary[str(Index)] try: value=entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':entry.getAttribute('Index'), 'Date':entry.getAttribute('Date')}
def show(
self, mode='text')
Displays a XMLLog either as formatted text in the command line or in a window (using wx)
def show(self,mode='text'): """ Displays a XMLLog either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML)
def update_Index_node_dictionary(
self)
Inheritance:
XMLLog
.update_Index_node_dictionary
Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document
def update_Index_node_dictionary(self): """ Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document""" self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')])
class XMLBase
The XMLBase Class is designed to be a container for xml data
class XMLBase(): """ The XMLBase Class is designed to be a container for xml data """ def __init__(self,file_path=None,**options): "Initializes the XML Base Class " # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"root", "style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_STYLE.xsl').replace('\\','/'), "specific_descriptor":'XML', "general_descriptor":'Document', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value # Define Method Aliases if they are available if METHOD_ALIASES: for command in alias(self): exec(command) #if the file path is not supplied create a new xml sheet if file_path is None: impl=getDOMImplementation() self.document=impl.createDocument(None,self.options['root'],None) # Should be a relative path for new_node=self.document.createProcessingInstruction('xml-stylesheet', u'type="text/xsl" href="%s"'%self.options['style_sheet']) self.document.insertBefore(new_node,self.document.documentElement) if DEFAULT_FILE_NAME is None: self.path=auto_name(self.options["specific_descriptor"], self.options["general_descriptor"], self.options["directory"], self.options["extension"]) else: # Just a backup plan if the python path is messed up self.path=DEFAULT_FILE_NAME else: file_in=open(file_path,'r') self.document=xml.dom.minidom.parse(file_in) file_in.close() self.path=file_path def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close() if XSLT_CAPABLE: def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML) def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close() def show(self,mode='Window'): """ Displays a XML Document either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop() def __str__(self): "Controls how XMLBAse is returned when a string function is called" return self.document.toprettyxml()
Ancestors (in MRO)
Instance variables
var options
Methods
def __init__(
self, file_path=None, **options)
Initializes the XML Base Class
def __init__(self,file_path=None,**options): "Initializes the XML Base Class " # This is a general pattern for adding a lot of options # The next more advanced thing to do is retrieve defaults from a settings file defaults={"root":"root", "style_sheet":os.path.join(XSLT_REPOSITORY,'DEFAULT_STYLE.xsl').replace('\\','/'), "specific_descriptor":'XML', "general_descriptor":'Document', "directory":None, "extension":'xml' } self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value # Define Method Aliases if they are available if METHOD_ALIASES: for command in alias(self): exec(command) #if the file path is not supplied create a new xml sheet if file_path is None: impl=getDOMImplementation() self.document=impl.createDocument(None,self.options['root'],None) # Should be a relative path for new_node=self.document.createProcessingInstruction('xml-stylesheet', u'type="text/xsl" href="%s"'%self.options['style_sheet']) self.document.insertBefore(new_node,self.document.documentElement) if DEFAULT_FILE_NAME is None: self.path=auto_name(self.options["specific_descriptor"], self.options["general_descriptor"], self.options["directory"], self.options["extension"]) else: # Just a backup plan if the python path is messed up self.path=DEFAULT_FILE_NAME else: file_in=open(file_path,'r') self.document=xml.dom.minidom.parse(file_in) file_in.close() self.path=file_path
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def show(
self, mode='Window')
Displays a XML Document either as formatted text in the command line or in a window (using wx)
def show(self,mode='Window'): """ Displays a XML Document either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML)
class XMLLog
Data container for a general XMLLog
class XMLLog(XMLBase): """ Data container for a general XMLLog""" def __init__(self,file_path=None,**options): """ Intializes the XMLLog""" # We add the defaults for the log pass and the options along defaults={"root":'Log', 'style_sheet':os.path.join(XSLT_REPOSITORY,'DEFAULT_LOG_STYLE.xsl').replace('\\','/'), 'entry_style_sheet':os.path.join(XSLT_REPOSITORY,'DEFAULT_LOG_STYLE.xsl').replace('\\','/'), 'specific_descriptor':'XML','general_descriptor':'Log'} self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) # TODO: Check how scalable a dictionary of nodes is self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')]) self.current_entry={} def add_entry(self,entry=None): """ Adds an entry element to the current log""" root=self.document.documentElement if entry is None: new_entry=self.document.createElement('Entry') value='' elif type(entry) is str: if re.search('<Entry>(.)+</Entry>',entry): new_document=xml.dom.minidom.parseString(new_entry) new_entry=new_document.documentElement else: new_document=xml.dom.minidom.parseString('<Entry>' +entry+'</Entry>') new_entry=new_document.documentElement else: new_entry=entry # Find the max of Index's and add 1 to make a new Index if len(self.Index_node_dictionary)==0: new_Index='1' else: max_Index=max([int(Index) for Index in self.Index_node_dictionary.keys()]) new_Index=str(max_Index+1) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(new_Index)) if new_entry.getAttribute('Date'): pass else: # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() try: value=new_entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':new_entry.getAttribute('Index'), 'Date':new_entry.getAttribute('Date')} def edit_entry(self,old_Index,new_value=None,new_Index=None,new_Date=None): """Edits and existing entry by replacing the existing values with new ones""" node=self.get_entry(str(old_Index)) if not new_value is None: new_text_node=self.document.createTextNode(new_value) try: old_text_node=node.childNodes[0] node.removeChild(old_text_node) except: pass node.appendChild(new_text_node) elif not new_Index is None: node.setAttribute('Index',new_Index) elif not new_Date is None: node.setAttribute('Date',new_Date) self.current_entry={'Tag':'Entry','Value':node.childNodes[0].data,'Index':node.getAttribute('Index'), 'Date':node.getAttribute('Date')} def get_entry(self,Index): """ Returns the entry selcted by Index""" return self.Index_node_dictionary[str(Index)] def set_current_entry(self,Index=-1): """Sets self.current_entry """ entry=self.Index_node_dictionary[str(Index)] try: value=entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':entry.getAttribute('Index'), 'Date':entry.getAttribute('Date')} def remove_entry(self,Index): """ Removes the entry using the Index attribute""" root=self.document.documentElement root.removeChild(self.Index_node_dictionary[Index]) self.update_Index_node_dictionary() def add_description(self,description=None): """ Adds an entry with Index='-1' which holds data about the log itself""" root=self.document.documentElement new_entry=self.document.createElement('Entry') if not description is None: text_node=self.document.createTextNode(description) new_entry.appendChild(text_node) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(-1)) # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() def update_Index_node_dictionary(self): """ Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document""" self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')]) # if the XSLT engine loaded then define a transformation to HTML if XSLT_CAPABLE: def current_entry_to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: XSLT=self.options['entry_style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) current_entry_XML=self.Index_node_dictionary[self.current_entry['Index']] HTML=XSL_transform(etree.XML(current_entry_XML.toxml())) return HTML # TODO: Make show and display function work well def previous_entry(self): """Sets current entry to the one before""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index-1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if min(Indices)<Index: Indices.sort() new_Index=Indices[Indices.index(Index)-1] else: Indices.remove(Index) if len(Indices)>0: new_Index=max(Indices) else: new_Index=Index self.set_current_entry(new_Index) def next_entry(self): """Sets current entry to the one after""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index+1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if max(Indices)>Index: Indices.sort() new_Index=Indices[Indices.index(Index)+1] else: Indices.remove(Index) new_Index=min(Indices) self.set_current_entry(new_Index) def show(self,mode='text'): """ Displays a XMLLog either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop() def __add__(object,right): """Controls Behavior of two XMLLogs added using the + operator""" new_log=object for entry in right.document.getElementsByTagName('Entry'): if entry.getAttribute('Index')=='-1': pass else: new_log.add_entry(entry) return new_log
Ancestors (in MRO)
Instance variables
var Index_node_dictionary
var current_entry
Methods
def __init__(
self, file_path=None, **options)
Intializes the XMLLog
def __init__(self,file_path=None,**options): """ Intializes the XMLLog""" # We add the defaults for the log pass and the options along defaults={"root":'Log', 'style_sheet':os.path.join(XSLT_REPOSITORY,'DEFAULT_LOG_STYLE.xsl').replace('\\','/'), 'entry_style_sheet':os.path.join(XSLT_REPOSITORY,'DEFAULT_LOG_STYLE.xsl').replace('\\','/'), 'specific_descriptor':'XML','general_descriptor':'Log'} self.options={} for key,value in defaults.iteritems(): self.options[key]=value for key,value in options.iteritems(): self.options[key]=value XMLBase.__init__(self,file_path,**self.options) # TODO: Check how scalable a dictionary of nodes is self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')]) self.current_entry={}
def add_description(
self, description=None)
Adds an entry with Index='-1' which holds data about the log itself
def add_description(self,description=None): """ Adds an entry with Index='-1' which holds data about the log itself""" root=self.document.documentElement new_entry=self.document.createElement('Entry') if not description is None: text_node=self.document.createTextNode(description) new_entry.appendChild(text_node) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(-1)) # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary()
def add_entry(
self, entry=None)
Adds an entry element to the current log
def add_entry(self,entry=None): """ Adds an entry element to the current log""" root=self.document.documentElement if entry is None: new_entry=self.document.createElement('Entry') value='' elif type(entry) is str: if re.search('<Entry>(.)+</Entry>',entry): new_document=xml.dom.minidom.parseString(new_entry) new_entry=new_document.documentElement else: new_document=xml.dom.minidom.parseString('<Entry>' +entry+'</Entry>') new_entry=new_document.documentElement else: new_entry=entry # Find the max of Index's and add 1 to make a new Index if len(self.Index_node_dictionary)==0: new_Index='1' else: max_Index=max([int(Index) for Index in self.Index_node_dictionary.keys()]) new_Index=str(max_Index+1) # Add the Index attribute to the new entry Index_attribute=self.document.createAttribute('Index') new_entry.setAttributeNode(Index_attribute) new_entry.setAttribute('Index',str(new_Index)) if new_entry.getAttribute('Date'): pass else: # Add the Date attribute, this is the time when the entry was logged date=datetime.datetime.utcnow().isoformat() Date_attribute=self.document.createAttribute('Date') new_entry.setAttributeNode(Date_attribute) new_entry.setAttribute('Date',str(date)) # Now append the new Child root.appendChild(new_entry) self.update_Index_node_dictionary() try: value=new_entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':new_entry.getAttribute('Index'), 'Date':new_entry.getAttribute('Date')}
def current_entry_to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def current_entry_to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: XSLT=self.options['entry_style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) current_entry_XML=self.Index_node_dictionary[self.current_entry['Index']] HTML=XSL_transform(etree.XML(current_entry_XML.toxml())) return HTML
def edit_entry(
self, old_Index, new_value=None, new_Index=None, new_Date=None)
Edits and existing entry by replacing the existing values with new ones
def edit_entry(self,old_Index,new_value=None,new_Index=None,new_Date=None): """Edits and existing entry by replacing the existing values with new ones""" node=self.get_entry(str(old_Index)) if not new_value is None: new_text_node=self.document.createTextNode(new_value) try: old_text_node=node.childNodes[0] node.removeChild(old_text_node) except: pass node.appendChild(new_text_node) elif not new_Index is None: node.setAttribute('Index',new_Index) elif not new_Date is None: node.setAttribute('Date',new_Date) self.current_entry={'Tag':'Entry','Value':node.childNodes[0].data,'Index':node.getAttribute('Index'), 'Date':node.getAttribute('Date')}
def get_entry(
self, Index)
Returns the entry selcted by Index
def get_entry(self,Index): """ Returns the entry selcted by Index""" return self.Index_node_dictionary[str(Index)]
def next_entry(
self)
Sets current entry to the one after
def next_entry(self): """Sets current entry to the one after""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index+1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if max(Indices)>Index: Indices.sort() new_Index=Indices[Indices.index(Index)+1] else: Indices.remove(Index) new_Index=min(Indices) self.set_current_entry(new_Index)
def previous_entry(
self)
Sets current entry to the one before
def previous_entry(self): """Sets current entry to the one before""" if len(self.current_entry)>0: Index=int(self.current_entry['Index']) else: return new_Index=Index-1 try: self.set_current_entry(new_Index) except KeyError: Indices=map(lambda x:int(x),self.Index_node_dictionary.keys()) if min(Indices)<Index: Indices.sort() new_Index=Indices[Indices.index(Index)-1] else: Indices.remove(Index) if len(Indices)>0: new_Index=max(Indices) else: new_Index=Index self.set_current_entry(new_Index)
def remove_entry(
self, Index)
Removes the entry using the Index attribute
def remove_entry(self,Index): """ Removes the entry using the Index attribute""" root=self.document.documentElement root.removeChild(self.Index_node_dictionary[Index]) self.update_Index_node_dictionary()
def save(
self, path=None)
" Saves as an XML file
def save(self,path=None): """" Saves as an XML file""" if path is None: path=self.path file_out=open(path,'w') file_out.write(self.document.toprettyxml()) file_out.close()
def save_HTML(
self, XSLT=None, file_path=None)
Inheritance:
XMLBase
.save_HTML
Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')
def save_HTML(self,XSLT=None,file_path=None): """Saves a HTML transformation of the XML document using XLST at file_path. Defaults to an XLST in self.options["XSLT"] and file_path=self.path.replace('.xml','.html')""" HTML=self.to_HTML(XSLT=XSLT) #print type(HTML) if file_path is None: file_path=self.path.replace('.xml','.html') out_file=open(file_path,'w') out_file.write(HTML) out_file.close()
def set_current_entry(
self, Index=-1)
Sets self.current_entry
def set_current_entry(self,Index=-1): """Sets self.current_entry """ entry=self.Index_node_dictionary[str(Index)] try: value=entry.childNodes[0].data except: value='' self.current_entry={'Tag':'Entry','Value':value,'Index':entry.getAttribute('Index'), 'Date':entry.getAttribute('Date')}
def show(
self, mode='text')
Displays a XMLLog either as formatted text in the command line or in a window (using wx)
def show(self,mode='text'): """ Displays a XMLLog either as formatted text in the command line or in a window (using wx)""" def tag_to_tagName(tag): tagName=tag.replace('<','') tagName=tagName.replace('/','') tagName=tagName.replace('>','') return tagName if mode in ['text','txt','cmd line','cmd']: for node in self.document.getElementsByTagName('Entry'): print 'Entry Index: %s \tDate: %s'%(node.getAttribute('Index'), node.getAttribute('Date')) print node.firstChild.nodeValue elif re.search('xml',mode,re.IGNORECASE): for node in self.document.getElementsByTagName('Entry'): print node.toprettyxml() elif re.search('Window|wx',mode,re.IGNORECASE): try: import wx import wx.html except: print 'Cannot locate wx, please add to sys.path' app = wx.App(False) frame=wx.Frame(None) html_window=wx.html.HtmlWindow(frame) html_window.SetPage(str(self.to_HTML())) frame.Show() app.MainLoop()
def to_HTML(
self, XSLT=None)
Returns HTML string by applying a XSL to the XML document
def to_HTML(self,XSLT=None): """ Returns HTML string by applying a XSL to the XML document""" if XSLT is None: # For some reason an absolute path tends to break here, maybe a spaces in file names problem XSLT=self.options['style_sheet'] XSL_data=etree.parse(XSLT) XSL_transform=etree.XSLT(XSL_data) HTML=XSL_transform(etree.XML(self.document.toxml())) return str(HTML)
def update_Index_node_dictionary(
self)
Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document
def update_Index_node_dictionary(self): """ Re-creates the attribute self.Index_node_dictionary, using the current definition of self.document""" self.Index_node_dictionary=dict([(str(node.getAttribute('Index')), node) for node in \ self.document.getElementsByTagName('Entry')])