xml: change from amara to lxml
[treecutter.git] / treecutter / page.py
1 #!/usr/bin/python
2 import os
3 import subprocess
4 import tempfile
5 import re
6 from lxml import etree
7 from Cheetah.Template import Template
8 from pkg_resources import resource_filename, resource_listdir
9 from time import time
10 import treecutter.constants as const
11 from treecutter.tools import mkdir_p
12
13 class Page():
14     """Class representing a version of a webpage"""
15     def __init__(self,link,page):
16         self._link = link
17         self._file = page[1]
18         self._lang = page[0]
19         self._doc = None
20         self._resources = []
21         self._title = None
22         self._menu = None
23         self._rendered_article = None
24
25     def language(self):
26         return self._lang
27
28     def resources(self):
29         return set(self._resources)
30
31     def menu(self):
32         return self._menu
33
34     def set_article(self,art):
35         self._rendered_article = art
36
37     def prepare(self):
38         self._doc = etree.parse(self._file)
39         t = self._doc.xpath(u'/db:article/db:info/db:title',namespaces=const.XPATH)
40         if t:
41             self._title = unicode(t[0].text)
42         ta = self._doc.xpath(u'/db:article/db:info/db:titleabbrev',namespaces=const.XPATH)
43         if ta:
44             self._menu = unicode(ta[0].text)
45
46         dirname = os.path.dirname(self._file)
47         cwd = os.getcwd()
48         code  = self._doc.xpath(u"//xi:include[@parse='text']",namespaces=const.XPATH)
49         if code:
50             for c in code:
51                 href = c.get('href')
52                 alang = c.get('accept-language')
53                 xpointer = c.get('xpointer')
54                 (p, ext) = os.path.splitext(href)
55                 if ext in const.valid_scripts:
56                     exe = []
57                     script = os.path.join(os.path.abspath(dirname)+'/'+href)
58                     if os.path.isfile(script):
59                         exe.append(script)
60                     else:
61                         if href in resource_listdir('xinclude', ''):
62                             script = resource_filename('xinclude', href)
63                             exe.append(script)
64                         else:
65                             print "Script "+href+" in "+self._file+" missing"
66                     if alang:
67                         exe.append("lang="+alang)
68                     if xpointer:
69                         exe.append("xptr="+xpointer)
70                     print "  executing %15s" % (href),
71                     ts = time()
72                     os.chdir(dirname)
73                     xml = subprocess.Popen(exe,stdout=subprocess.PIPE,
74                                            stderr=subprocess.PIPE)
75                     (stdout, stderr) = xml.communicate()
76                     if stderr:
77                         print " ".join(exe)+" ERROR : [ "+stderr+" ]"
78                     os.chdir(cwd)
79                     te = time()
80                     print " [%5.2f s]  (%s)" % (round(te-ts,2),xpointer)
81                     xstr = etree.fromstring(stdout)
82 # inserting the generated code and remove the xinclude reference
83                     idp = c.getparent()
84                     idp.insert(idp.index(c)+1,xstr)
85                     idp.remove(c)
86
87         for r in self._doc.xpath(u"//db:link[@xlink:href]",namespaces=const.XPATH):
88             rf = os.path.join(dirname,r.get(const.XLINK+'href'))
89             if os.path.isfile(rf):
90                 self._resources.append(rf)
91         for i in self._doc.xpath(u"//db:imagedata[@fileref]",namespaces=const.XPATH):
92             im = os.path.join(dirname,i.get('fileref'))
93             if os.path.isfile(im):
94                 self._resources.append(im)
95         for i in self._doc.xpath(u"//html:form[@action]",namespaces=const.XPATH):
96             pyscript = re.split('\.py',i.get('action'),1)[0]+'.py'
97             im = os.path.join(dirname,pyscript)
98             if os.path.isfile(im):
99                 self._resources.append(im)
100
101     def render(self, style):
102
103 #        xslt_root = etree.XML(open(style+"docbook.xsl", 'r').read())
104 #        transform = etree.XSLT(xslt_root)
105 #        result = etree.tostring(transform(xml_root))
106
107         cwd = os.getcwd()
108         dirname = os.path.dirname(self._file)
109         os.chdir(dirname)
110         infile  = os.path.basename(tempfile.mktemp())
111         outfile = tempfile.mktemp()
112         tfi = open(infile,'w')
113         tfi.write(etree.tostring(self._doc,encoding='UTF-8',pretty_print=False))
114         tfi.close()
115 #  cmd = ["saxon-xslt-xinclude","-o",outfile,infile,style_xslt]
116         cmd = ["xsltproc","--xinclude","--output",outfile,style+"docbook.xsl",infile]
117         retcode = subprocess.call(cmd)
118         if retcode:
119             print 'Error: '+' '.join(cmd)+' Returncode ['+str(retcode)+']'
120         tfo = open(outfile,'r')
121         self._rendered_article = tfo.read()
122         tfo.close()
123         os.remove(infile)
124         os.remove(outfile)
125         os.chdir(cwd)
126
127     def template(self,sitemap,style,tdir):
128         htmlmenu =  sitemap.gen_menu(self._lang,None,"menu")
129         levelmenu = sitemap.gen_menu(self._lang,self,"tree")
130         langmenu = sitemap.lang_menu(self._lang,self._link)
131         template = Template(file=style+'index.'+self._lang+'.html.tmpl',
132                             searchList=[{'title':self._title},
133                                         {'menu':htmlmenu},
134                                         {'article':self._rendered_article},
135                                         {'levelmenu':levelmenu},
136                                         {'langmenu':langmenu}])
137         outfile = tdir+'html'.join(self._file.rsplit('xml',1))
138         mkdir_p(os.path.dirname(outfile))
139         out = open(outfile, 'w')
140         out.write(str(template))
141         out.close()