File:  [Repository] / ECHO_content / ECHO_xslt.py
Revision 1.11: download - view: text, annotated - select for diffs - revision graph
Thu Sep 14 14:31:53 2006 UTC (17 years, 9 months ago) by dwinter
Branches: MAIN
CVS tags: HEAD
minor

    1: ### XSLT Class ###
    2: ### setzt 4 suite vorraus ###
    3: from Acquisition import Implicit
    4: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
    5: from Globals import DTMLFile
    6: from ECHO_Nav import ECHO_pageTemplate
    7: from threading import Thread,Timer
    8: import threading
    9: from ECHO_helpers import *
   10: import ECHO_language
   11: import sys
   12: import urllib
   13: import urlparse
   14: from Ft.Xml.Domlette import Print, PrettyPrint
   15: from StringIO import StringIO
   16: from types import *
   17: from Globals import package_home
   18: import transaction
   19: 
   20: import os.path
   21: 
   22: import urllib
   23: 
   24: try:
   25:     from Ft.Xml.Xslt.Processor import Processor
   26:     from Ft.Xml import InputSource, EMPTY_NAMESPACE,Parse
   27:     from Ft.Xml.Domlette import NonvalidatingReader
   28: except:
   29:     print "4suite has to be installed"
   30: 
   31: 
   32: class getXML(Implicit):
   33:     """get XML thread"""
   34: 
   35:     def set(self,qs,xsl,result):
   36:         """set"""
   37:    
   38:         self._v_qs=qs
   39:         self.xsl=xsl
   40:         self.result=None        
   41: 
   42: #    def acquireLock(self):
   43: #    
   44: #         lock=getattr(self, "_v_lock", None)
   45: #         if not lock:
   46: #             self._v_lock=threading.Lock()
   47: #             lock=self._v_lock
   48: #         lock.acquire()
   49: #
   50: #    def releaseLock(self):
   51: #         # acquire() should have been called
   52: #         # about one second before. This means the volatile lock
   53: #         # should still be there
   54: #    
   55: #         self._v_lock.release()
   56: #        
   57:   
   58:     def __call__(self):
   59:         """wait"""
   60:         return True
   61:     
   62:     def run(self):
   63:         """call it"""
   64:         xml=""
   65: 
   66:         try:
   67:   
   68:             urlH=urllib.urlopen(self._v_qs)
   69:             xml=urlH.read()
   70:             urlH.close()
   71:             xsltproc=Processor()
   72:             document = InputSource.DefaultFactory.fromString(xml)
   73:             
   74:             stylesheet = InputSource.DefaultFactory.fromUri(self.xsl)
   75:             
   76:             xsltproc.appendStylesheet(stylesheet)
   77:             
   78:         
   79:             #print self.xsl
   80:             #print xsltproc.run(document)
   81:             tmp=xsltproc.run(document)
   82:             
   83:             self.result=tmp[0:]
   84:             
   85:         
   86:        	except:
   87:                
   88:                self.result="<html>error: %s %s<br>"%sys.exc_info()[0:2]
   89:                self.result+=xml
   90:                self.result+="</html>"
   91:         
   92:         
   93:     
   94:     def getResult(self):
   95: 
   96:         return self.result
   97: 
   98: from ZODB import DB
   99: from ZODB.FileStorage import FileStorage
  100: class ECHO_cache:
  101:     def __init__(self):
  102:         """init the storage"""
  103:         self.storage=FileStorage("/var/tmp/echo_cache.fs")
  104:         self.db=DB(self.storage)    
  105:         self.connection=self.db.open()
  106:         self.root=self.connection.root()
  107:     
  108:     def deleteObject(self,name,pn=None):
  109:         """delete an object from cache"""
  110:         fileStore=self.root.get(name,None)
  111:         if fileStore:
  112:             if not pn:
  113:                 del(self.root[name])
  114:             else:
  115:                 if self.root[name].get(pn,None):
  116:                     del(self.root[name][pn])
  117:                     
  118:         
  119:     def storeObject(self,name,pn,object):
  120:         """store an object"""
  121:         
  122:         if not self.root.get(name,None):
  123:             self.root[name]={}
  124:             
  125: 
  126:         #following is necessary to make clear that object has really changed for ZODB
  127:         tmp=self.root[name]
  128:         tmp[pn]=object
  129:         self.root[name]=tmp
  130:         transaction.get().commit()
  131:         return True
  132:    
  133:     def retrieveObject(self,name,pn):
  134:         """retrieve it"""
  135:         
  136:         fileStore=self.root.get(name,None)
  137:         if not fileStore:
  138:             return None
  139:         else:
  140:             return self.root[name].get(pn,None)
  141:         
  142: 
  143: class ECHO_xslt(ECHO_pageTemplate,ECHO_language.ECHO_language):
  144:     """ECHO_xslt classe"""
  145: 
  146:     meta_type="ECHO_xslt"
  147:     
  148:     cache=ECHO_cache() # cache for analysed pages
  149:     caching="yes"
  150:     
  151:     appendQueryString=True # add query string to the cgiUrl can be changed with addChanges
  152:     
  153:     passURL=False #use url from querystring parameter fn to retrieve the text and not the url in cgi-url can be changed with addChanges
  154:         
  155:     
  156:     results={}
  157:     manage_options=ECHO_pageTemplate.manage_options+(
  158:      {'label':'Change xml-ressource','action':'change_ECHO_xsltForm'},)
  159:      
  160:     def refreshTxt(self):
  161:         """txt fuer refresh"""
  162:         return """ 2;url=%s?repeat=%s """%(self.absolute_url(),self.threadName)
  163: 
  164:     def xslt(self):
  165:         """xslt"""
  166: 
  167:         return self.document_src()
  168: 
  169:     def change_ECHO_xsltForm(self):
  170:         """change form"""
  171:         pt=zptFile(self, 'zpt/ChangeECHO_xsltForm.zpt')
  172:         return pt()
  173: 
  174:     def addChanges(self,cgiUrl,appendQueryString=False,passURL=False,caching=False,RESPONSE=None):
  175:         """change the xslt, ueberschriebt addChanges in ECHO_PageTemplate"""
  176:     
  177:         if urlparse.urlparse(cgiUrl)[0]=="":#relative url in absolute
  178:             self.cgiUrl=urlparse.urljoin(self.absolute_url(), cgiUrl)
  179:         else:
  180:             self.cgiUrl=cgiUrl
  181:         
  182:         if appendQueryString: 
  183:             self.appendQueryString=True
  184:         else:
  185:             self.appendQueryString=False
  186:         
  187:         if passURL:
  188:             self.passURL=True
  189:         else:
  190:             self.passURL=False
  191:        
  192:         if caching:
  193:             self.caching="yes"
  194:         else:
  195:             self.caching="No"
  196:         
  197: 
  198:         if RESPONSE:
  199:             RESPONSE.redirect("manage_main")
  200:         
  201:     def index_html(self,repeat=None):
  202:         """standard ausgabe"""
  203: 
  204:         threadName=repeat
  205:         
  206:         if not threadName or threadName=="":
  207:             
  208:             #abwaertskompatibilitŠt mit altem nivht konfigurierbaren prototypen
  209:             
  210:             if getattr(self,'cgiUrl','')=='':
  211:                 self.cgiUrl="http://medea.mpiwg-berlin.mpg.de/cgi-bin/search/q1"
  212:                 
  213:             qs="%s%s"%(self.cgiUrl,self.REQUEST['QUERY_STRING'])
  214:             xsl=self.absolute_url()+"/xslt"
  215:             self._v_xmltrans=getXML().__of__(self)
  216:             #self._xmltrans.start()
  217:             thread=Thread(target=self._v_xmltrans)
  218:             thread.start()
  219:             self._v_xmltrans.set(qs,xsl,None)
  220:             self._v_xmltrans.run()
  221:             
  222:             
  223:             self.threadName=thread.getName()[0:]
  224:             wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
  225:             if wait_template:
  226:                 return wait_template[0][1]()
  227:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','xsltWait.zpt')).__of__(self)
  228:             return pt()
  229:             #_v_xmltrans.run()
  230:         
  231:         else:
  232:             
  233:             if (self._v_xmltrans.getResult()==None):
  234: 
  235:                 wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
  236:                 if wait_template:
  237:                         return wait_template[0][1]()
  238:                 
  239:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','xsltWait.zpt')).__of__(self)
  240:                 return pt()
  241:             else:
  242:                 return self._v_xmltrans.getResult()
  243: 
  244:     
  245:     def getText(self):
  246:         """print nur den text"""
  247:         qs,baseUri=self.getTextInput()
  248:         self.REQUEST.RESPONSE.redirect(qs)
  249: 
  250:     def deleteCache(self):
  251:         """deletefrom cache"""
  252:         fn=self.REQUEST['fn']
  253:         self.cache.deleteObject(fn)
  254:         
  255:     def getPageLex(self,_pn="1",_id=None,_caching=None):
  256:         """getpage mit lexikalischer analyse und xslt transform
  257:         if _caching=yes dann wird die lwxikalisch analysierte seite in einem cache abgespeichert
  258:         """
  259: 
  260:         if not _caching:
  261:             _caching=self.caching
  262:             
  263:         fn=self.REQUEST['fn']
  264: 
  265:         if not _id:
  266:             fromCache=self.cache.retrieveObject(fn,_pn)
  267:      
  268:             if fromCache and _caching=="yes":
  269:               
  270:                 txt = fromCache
  271:             else:
  272:                 txt=self.tagLex(nr=_pn)   
  273:              
  274:                 self.cache.storeObject(fn,_pn,txt[0:])
  275:             
  276:         else:
  277:            txt=self.tagLex(id=_id)
  278:            
  279:         xsl=self.xslt()
  280:         
  281:         xsltproc=Processor()
  282:         if type(txt)==UnicodeType:
  283:             document = InputSource.DefaultFactory.fromString(txt.encode('utf-8'))
  284:         else:
  285:             document = InputSource.DefaultFactory.fromString(txt)
  286:         stylesheet = InputSource.DefaultFactory.fromString(xsl)
  287:         xsltproc.appendStylesheet(stylesheet)
  288:         tmp=xsltproc.run(document)
  289:         #bugfix for digilib images which doesn't accept &amp;
  290:         tmp=tmp.replace("&amp;","&")
  291:         return tmp[0:]
  292:             
  293:     def getTextInput(self):
  294:         """get the text
  295:         wie der text geholt wird liegt an der konfiguration,
  296:         is appendQueryString gesetzt, dann wir jeweils der Querystring an vorgebenen url gesetzt, erwartet wird fn=
  297:         fŸr den Pfad, is passURL gesetzt, dann wird falls fn= eine vollstŠndige url enthŠlt, diese anstelle der in cgiurl definierten genommen.
  298:         """
  299:         
  300:         if getattr(self,'passURL',False) and self.REQUEST.has_key('fn') and (urlparse.urlparse(self.REQUEST['fn'])[0]=='http'):
  301:             qs=self.REQUEST['fn']
  302:             baseUri=qs
  303:         elif getattr(self,'pappendQueryString',True):
  304:             qs="%s%s"%(self.cgiUrl,self.REQUEST['QUERY_STRING'])
  305:             baseUri=self.cgiUrl
  306:         else:
  307:             qs="%s"%(self.cgiUrl)
  308:             baseUri=self.cgiUrl
  309:         
  310:         #fact= InputSource.DefaultFactory.fromUri(qs)
  311:         return qs,baseUri
  312:         #return InputSource.InputSource(fact)
  313:         #xmlt=urllib.urlopen(qs).read()
  314:         
  315:     def getPage(self,_pn="-1",_id=None,REQUEST=None,_caching=None):
  316:         """get a page from an xml"""
  317:         
  318:         if not _caching:
  319:             _caching=self.caching
  320:             
  321:         pn=int(_pn)-1
  322:         if pn<0 and (not _id):
  323:             if REQUEST:
  324:                 return "Sorry, pagenumbers have to be greater than 0"
  325:             else:
  326:                 return None
  327:        
  328:         xmlt,self.baseUri=self.getTextInput()
  329:         
  330:         #get the text from cache, if existing
  331:         fromCache=self.cache.retrieveObject(self.baseUri,"-1")
  332:         if fromCache and _caching=="yes":
  333:           
  334:             txt = fromCache
  335:         else:
  336: 
  337:             txt=urllib.urlopen(xmlt).read()
  338:             
  339:             self.cache.storeObject(self.baseUri,"-1",txt)
  340:         
  341:         dom=NonvalidatingReader.parseString(txt,self.baseUri)
  342:         
  343:         #pb should have a namespache
  344: 
  345:         pbs=dom.xpath("//mpiwg:pb",explicitNss={'mpiwg':'http://www.mpiwg-berlin.mpg.de/namespace'})
  346:         
  347:         if len(pbs)==0: # versuche nochmal ohne
  348:             pbs=dom.xpath("//pb")
  349: 
  350:         if _id:
  351:             #suche wieviele pb for der id
  352:             
  353:             
  354:             idpb=dom.xpath("//*[@id='%s']/preceding::node()/mpiwg:pb"%_id,explicitNss={'html':'http://test.de','mpiwg':'http://www.mpiwg-berlin.mpg.de/namespace'})
  355:             if len(idpb)==0:
  356:                 idpb=dom.xpath("//*[@id='%s']/preceding::node()/pb"%_id)
  357:          
  358:             if len(idpb)==0:
  359:                         k=0
  360:                         for node in dom.xpath("//*[@id='%s']//preceding::node()"%_id,explicitNss={'html':'http://test.de','mpiwg':'http://www.mpiwg-berlin.mpg.de/namespace'}):
  361:                             if getattr(node,'tagName',"")=="mpiwg:pb":
  362:                                 k+=1
  363:             else:
  364:                 k=len(idpb)
  365:             pn=k-1 #-1 wegen Seitenzahlzaehlung startet mit 0
  366:             
  367:         if pn > len(pbs):
  368:             if REQUEST:
  369:                 return "Sorry, pagenumber %s does not exit"%(pn+1)
  370:             else:
  371:                 return None
  372:             
  373:         beginNode=pbs[pn] #take the n'th pb
  374: 
  375:         if not (pn==len(pbs)-1): # nicht die letzte Seite
  376:             endNode=pbs[pn+1]
  377:         else:
  378:             endNode=None
  379:         
  380:         deleteNodes=beginNode.xpath('preceding::node()')
  381:         if endNode:
  382:             deleteNodes+=endNode.xpath('following::node()')
  383:         for node in deleteNodes:
  384:             try:
  385:                 parent=node.xpath("..")
  386:            
  387:                 if parent:
  388:                     parent[0].removeChild(node)
  389:             except:
  390:                 zLOG.LOG("ECHO_Resource (getAccessRightMD)", zLOG.INFO,"%s (%s)"%sys.exc_info()[0:2])
  391:         strio = StringIO()
  392:         PrettyPrint(dom,strio) 
  393:         xmlstr = strio.getvalue()
  394:         
  395:         return xmlstr
  396: 
  397: 
  398:         
  399: def manage_addECHO_xsltForm(self):
  400:     """Form for adding"""
  401:     pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','AddECHO_xslt.zpt')).__of__(self)
  402:     return pt()
  403: 
  404: from urllib import quote
  405: 
  406: 
  407: def manage_addECHO_xslt(self, id, label, weight= 0,contentType=0,title=None, text=None, cgiUrl=None,
  408:                            REQUEST=None, submit=None):
  409:     "Add a Page Template with optional file content."
  410: 
  411:     
  412:     id = str(id)
  413:     if REQUEST is None:
  414:         self._setObject(id, ECHO_xslt(id, text))
  415:         ob = getattr(self, id)
  416:         setattr(ob,'weight',weight)
  417:         setattr(ob,'label',label)
  418:         setattr(ob,'contentType',contentType)
  419:         if title:
  420:             ob.pt_setTitle(title)
  421:         return ob
  422:         setattr(ob,'cgiUrl',cgiUrl)
  423:     else:
  424:         file = REQUEST.form.get('file')
  425:         headers = getattr(file, 'headers', None)
  426:         if headers is None or not file.filename:
  427:             zpt = ECHO_xslt(id)
  428:         else:
  429:             zpt = ECHO_xslt(id, file, headers.get('contentType'))
  430: 
  431:         self._setObject(id, zpt)
  432:         ob = getattr(self, id)
  433:         setattr(ob,'weight',weight)
  434:         setattr(ob,'label',label)
  435:         setattr(ob,'cgiUrl',cgiUrl)
  436:         if title:
  437:             ob.pt_setTitle(title)
  438:         
  439:         try:
  440:             u = self.DestinationURL()
  441:         except AttributeError:
  442:             u = REQUEST['URL1']
  443: 
  444:         if submit == " Add and Edit ":
  445:             u = "%s/%s" % (u, quote(id))
  446:         REQUEST.RESPONSE.redirect(u+'/manage_main')
  447:     return ''
  448: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>