changeset 14:05933707897f

NEW - # 12: create table and upload data https://it-dev.mpiwg-berlin.mpg.de/tracs/GIS/ticket/12
author casties
date Fri, 13 Aug 2010 18:34:46 +0200
parents e2c73c077533
children 5e3edf980813
files RestDbInterface.py
diffstat 1 files changed, 170 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/RestDbInterface.py	Thu Aug 12 20:04:57 2010 +0200
+++ b/RestDbInterface.py	Fri Aug 13 18:34:46 2010 +0200
@@ -19,6 +19,18 @@
 from Products.ZSQLMethods.SQL import SQLConnectionIDs
 
 
+def getTextFromNode(nodename):
+    """get the cdata content of a XML node"""
+    if nodename is None:
+        return ""
+    nodelist=nodename.childNodes
+    rc = ""
+    for node in nodelist:
+        if node.nodeType == node.TEXT_NODE:
+           rc = rc + node.data
+    return rc
+
+
 class RestDbInterface(Folder):
     """Object for RESTful database queries
     path schema: /db/{schema}/{table}/
@@ -237,10 +249,168 @@
         # TODO: really look up schemas
         data={'fields': (('schemas',),), 'rows': [('public',),]}
         return data
+    
+    def createEmptyTable(self,schema,table,fields):
+        """create a table with the given fields
+           returns list of created fields"""
+        sqlFields = []
+        for f in fields:
+            if isinstance(f,dict):
+                # {name: XX, type: YY}
+                name = sqlName(f['name'])
+                type = f['type']
+            
+            else:
+                # name only
+                name = sqlName(f)
+                type = 'text'
+                
+            sqlFields.append({'name':name, 'type':type})
+            
+        # drop table if it exists
+        try:
+            res = executeSQL('drop table "%s.%s"'%(schema,table))
+        except:
+            pass
+        
+        fieldString = ", ".join(["%s %s"%(f['name'],f['type']) for f in sqlFields])
+        sqlString = 'create table "%s.%s" (%s)'%(schema,table,fieldString)
+        ret = executeSQL(sqlString)
+        
+        return sqlFields
+        
+        
 
     def createTableFromXML(self,schema,table,data):
         """create or replace a table with the given XML data"""
         logging.debug("createTableFromXML schema=%s table=%s data=%s"%(schema,table,data))
+        self.importExcelXML(table, data)
+        
+    def importExcelXML(self,table,data,fieldNamesOnly=False):
+        '''
+        Import XML file in Excel format into the table
+        @param table: name of the table the xml shall be imported into
+        @param containerTagName: XML-Tag which describes a dataset
+        @param data: data to be imported
+        @param identify: (optional) field res. tag which identifies a entry uniquely for updating purposes.
+        @param RESPONSE: (optional)
+        '''
+        from xml.dom.pulldom import parseString,parse
+        
+        namespace = "urn:schemas-microsoft-com:office:spreadsheet"
+        containerTagName = "Table"
+        rowTagName = "Row"
+        dataTagName = "Data"
+        fieldNames = []
+        sqlFields = []
+        sqlInsert = None
+        
+        logging.debug("import excel xml")
+        
+        ret=""
+        if isinstance(data, str):
+            logging.debug("importXML reading string data")
+            doc=parseString(data)
+        else:
+            logging.debug("importXML reading file data")
+            doc=parse(data)
+            
+        cnt = 0
+        while True:
+            node=doc.getEvent()
+
+            if node is None:
+                break
+            
+            else:
+                if node[1].localName is not None:
+                    tagName = node[1].localName.lower()
+                else:
+                    # ignore non-tag nodes
+                    continue
+                
+                if  tagName == containerTagName.lower(): # make everything case insensitive
+                    # start of container -- do we need this?
+                    cnt = 0
+                    continue
+                
+                if tagName == rowTagName.lower():
+                    # start of row
+                    doc.expandNode(node[1])
+                    cnt += 1
+                    if cnt == 1:
+                        # first row -- field names
+                        names=node[1].getElementsByTagNameNS(namespace, dataTagName)
+                        for name in names:
+                            fn = getTextFromNode(name)
+                            fieldNames.append(fn)
+                            
+                        if fieldNamesOnly:
+                            # return just field names
+                            return fieldNames
+                        
+                        # create table
+                        sqlFields = self.createEmptyTable(schema, table, fieldNames)
+                        fieldString = ", ".join(["%s"%f['name'] for f in sqlFields])
+                        valString = ", ".join(["%s" for f in sqlFields])
+                        sqlInsert = 'insert into "%s.%s" (%s) values (%s)'%(schema,table,fieldString,valString)
+                        
+                    else:
+                        # following rows are data
+                        dataNodes=node[1].getElementsByTagNameNS(namespace, dataTagName)
+                        data = []
+                        for dataNode in dataNodes:
+                            val = getTextFromNode(dataNodes)
+                            data.append(val)
+                            
+                        self.executeSQL(sqlInsert, data)
+                        
+
+                    continue
+                    
+                    '''dataSet={}
+                    for col in node[1].childNodes:
+                        if col.nodeType is col.ELEMENT_NODE: 
+                            data=col.nodeName
+                            dataSet[data]=getTextFromNode(col)
+
+                    update=False
+                    
+                    if identify:
+
+                        field=dataSet[identify]
+
+                        searchStr="""select %s from %s where %s = '%s'"""%(identify,table,identify,field)
+                        logger("import xml",logging.INFO,searchStr)
+                        search=self.ZSQLSimpleSearch(searchStr)
+                        if search:
+                            update=True
+                    
+                    if update:
+                        tmp=[]
+                        for fieldName in dataSet.keys():
+                            tmp.append("""%s = %s"""%(fieldName,self.ZSQLQuote(dataSet[fieldName])))
+                        setStr=",".join(tmp)
+
+                        field=dataSet[identify]
+                  
+                        queryStr="""UPDATE %s SET %s WHERE %s = '%s' """%(table,setStr,identify,field)
+                        logger("update xml",logging.INFO,queryStr)
+                        self.ZSQLSimpleSearch(queryStr)
+                        ret+="ud: %s \n"%field
+
+                    else:
+                        fields=",".join(dataSet.keys())
+                        values=",".join([""" %s """%self.ZSQLQuote(dataSet[x]) for x in dataSet.keys()])
+                  
+                        
+                        queryStr="""INSERT INTO %s  (%s) VALUES (%s)"""%(table,fields,values)
+                        self.ZSQLSimpleSearch(queryStr)
+                        logger("update xml",logging.INFO,queryStr)
+                    '''
+                      
+        logging.debug("XML import field names: %s"%(fieldNames))
+        return ret
          
         
     def manage_editRestDbInterface(self, title=None, connection_id=None,