source: TI07-MOLES/trunk/StubB/XSLT/browse/portal/cgi/Utilities.py @ 959

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI07-MOLES/trunk/StubB/XSLT/browse/portal/cgi/Utilities.py@959
Revision 959, 4.1 KB checked in by lawrence, 15 years ago (diff)

Utility to support HTML presentation of vanilla xml (including highlight of
matched search terms) for discovery and browse.

Line 
1from collections import deque # python 2.4
2import ConfigParser
3import os
4import re
5
6def cleanup(string):
7    '''This is a hack to make sure that xml doesn't contain any naughty & characters alone'''
8    #match ? but not (?! if it's followed by alphanumeric \w characters + and a semicolon ;
9    return re.sub(r'&(?!\w+;)', '&', string)
10
11class myConfig:
12        ''' Handle missing sections and variables in a config file a bit gracefully '''
13        def __init__(self,configfile):
14                self.config=ConfigParser.ConfigParser()
15                if not os.path.exists(configfile):
16                        raise 'No config file'
17                self.config.read(configfile)
18                logfile=self.get('logging','debugLog',None)
19                self.logfile=None
20                if logfile is not None:
21                        self.logfile=open(logfile,'a')
22
23        def get(self,section,key,default=None):
24                try:
25                        return self.config.get(section,key)
26                except:
27                        return default
28       
29        def log(self,string):
30                self.logfile.write(string+'\n')
31               
32class Response:
33        ''' Holds all the parts of the response to an HTML get or post '''
34        def __init__(self):
35                self.headers=[]
36                self.cookie=None
37                self.contentType='text/html'
38                self.content=''
39        def write(self,out):
40                for name,value in self.headers:
41                        out.write("%s: %s\n"( name,value))
42                if self.cookie:
43                        out.write("%s\n"%self.cookie)
44                out.write("Content-type: %s\n"%self.contentType)
45                out.write("\n")
46                out.write(self.content)
47
48class RingBuffer(deque):
49    #deque is a python 2.4 class!
50    #credit http://www.onlamp.com/pub/a/python/excerpt/pythonckbk_chap1/index1.html
51    def __init__(self, size_max):
52        deque.__init__(self)
53        self.size_max = size_max
54    def append(self, datum):
55        deque.append(self, datum)
56        if len(self) > self.size_max:
57            self.popleft( )
58    def tolist(self):
59        return list(self)
60
61def wrapGetText(element,xpathExpression,multiple=0):
62        ''' Wraps a call to ET to get a text object in an error handler '''
63        if multiple:
64                r=element.findall(xpathExpression)
65        else:
66                r=[element.find(xpathExpression),]
67        try:
68                rr=[i.text for i in r]
69        except:
70                rr=['',]
71        if multiple: 
72                return rr
73        else: return rr[0] 
74
75def PrettyPrint(elem,indent='',html=0,space='   '):
76        '''Lightweight pretty printing of elementTree elements'''
77        def estrip(elem):
78                ''' Just want to get rid of unwanted whitespace '''
79                if elem is None:
80                        return ''
81                else:
82                        return elem.strip()
83        strAttrib=''
84        for att in elem.attrib:
85                strAttrib+=' %s="%s"'%(att,elem.attrib[att])
86        result='%s<%s%s>%s'%(indent,elem.tag,strAttrib,estrip(elem.text))
87        children=len(elem)
88        if children:
89                for item in elem:
90                        result+='\n'+PrettyPrint(item,indent=indent+space)
91                result+='\n%s%s</%s>'%(indent,estrip(item.tail),elem.tag)
92        else:
93                result+='</%s>'%(elem.tag)
94        return result
95       
96def PrettyPrintHTML(elem,matchList=[]):
97    '''Lightweight HTML pretty printing of elementTree elements + highlight
98    any words which occur in the element text (and tails) which occur in matchList,
99    and formatted using a css something like this:
100    ===
101    DIV.xmlElem {PADDING-LEFT: 20px;}
102    .xmlAttrVal {COLOR:Red; }
103    .xmlAttrTyp {COLOR:Green; }
104    .xmlElemTag {COLOR:Blue; }
105.   highlight {BACKGROUND-COLOR:Yellow; }
106    ===
107    '''
108    def span(x,c): return '<span class="%s">%s</span>'%(c,x)
109    def div(x,c): return '<div class="%s">%s</div>'%(c,x)
110    def match(x): 
111        if x is None: return ''
112        for w in matchList: x=re.sub(w,span(w,'highlight'),x)
113        return x
114    lt,gt='<b>&lt;</b>','<b>&gt;</b>'
115    strAttrib=''
116    for att in elem.attrib:
117        strAttrib+=' %s="%s"'%(span(att,'xmlAttrTyp'),span(elem.attrib[att],'xmlAttrVal'))
118    result='%s%s%s%s%s'%(lt,span(elem.tag,"xmlElemTag"),strAttrib,gt,match(elem.text))
119    children=len(elem)
120    if children:
121        for item in elem:
122            result+=PrettyPrintHTML(item)
123        result+='%s%s/%s%s'%(match(item.tail),lt,span(elem.tag,'xmlElemTag'),gt)
124    else:
125        result+='%s/%s%s'%(lt,span(elem.tag,'xmlElemTag'),gt)
126    return div(result,'xmlElem')
127
128if __name__=="__main__":
129    x='''<test attr='something'>some content with <a href="target"> display</a> url</test>'''
130    import ElementTree as ET
131    y=ET.fromstring(x)
132    print PrettyPrintHTML(y,['content',])
133    print PrettyPrint(y)
134   
Note: See TracBrowser for help on using the repository browser.