Premiere version : mise en route du suivi.
[auf_roundup.git] / roundup / cgi / TAL / .svn / text-base / TALParser.py.svn-base
1 ##############################################################################
2 #
3 # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """
15 Parse XML and compile to TALInterpreter intermediate code.
16 """
17
18 from XMLParser import XMLParser
19 from TALDefs import XML_NS, ZOPE_I18N_NS, ZOPE_METAL_NS, ZOPE_TAL_NS
20 from TALGenerator import TALGenerator
21
22 class TALParser(XMLParser):
23
24     ordered_attributes = 1
25
26     def __init__(self, gen=None): # Override
27         XMLParser.__init__(self)
28         if gen is None:
29             gen = TALGenerator()
30         self.gen = gen
31         self.nsStack = []
32         self.nsDict = {XML_NS: 'xml'}
33         self.nsNew = []
34
35     def getCode(self):
36         return self.gen.getCode()
37
38     def getWarnings(self):
39         return ()
40
41     def StartNamespaceDeclHandler(self, prefix, uri):
42         self.nsStack.append(self.nsDict.copy())
43         self.nsDict[uri] = prefix
44         self.nsNew.append((prefix, uri))
45
46     def EndNamespaceDeclHandler(self, prefix):
47         self.nsDict = self.nsStack.pop()
48
49     def StartElementHandler(self, name, attrs):
50         if self.ordered_attributes:
51             # attrs is a list of alternating names and values
52             attrlist = []
53             for i in range(0, len(attrs), 2):
54                 key = attrs[i]
55                 value = attrs[i+1]
56                 attrlist.append((key, value))
57         else:
58             # attrs is a dict of {name: value}
59             attrlist = attrs.items()
60             attrlist.sort() # For definiteness
61         name, attrlist, taldict, metaldict, i18ndict \
62               = self.process_ns(name, attrlist)
63         attrlist = self.xmlnsattrs() + attrlist
64         self.gen.emitStartElement(name, attrlist, taldict, metaldict, i18ndict)
65
66     def process_ns(self, name, attrlist):
67         taldict = {}
68         metaldict = {}
69         i18ndict = {}
70         fixedattrlist = []
71         name, namebase, namens = self.fixname(name)
72         for key, value in attrlist:
73             key, keybase, keyns = self.fixname(key)
74             ns = keyns or namens # default to tag namespace
75             item = key, value
76             if ns == 'metal':
77                 metaldict[keybase] = value
78                 item = item + ("metal",)
79             elif ns == 'tal':
80                 taldict[keybase] = value
81                 item = item + ("tal",)
82             elif ns == 'i18n':
83                 assert 0, "dealing with i18n: " + `(keybase, value)`
84                 i18ndict[keybase] = value
85                 item = item + ('i18n',)
86             fixedattrlist.append(item)
87         if namens in ('metal', 'tal', 'i18n'):
88             taldict['tal tag'] = namens
89         return name, fixedattrlist, taldict, metaldict, i18ndict
90
91     def xmlnsattrs(self):
92         newlist = []
93         for prefix, uri in self.nsNew:
94             if prefix:
95                 key = "xmlns:" + prefix
96             else:
97                 key = "xmlns"
98             if uri in (ZOPE_METAL_NS, ZOPE_TAL_NS, ZOPE_I18N_NS):
99                 item = (key, uri, "xmlns")
100             else:
101                 item = (key, uri)
102             newlist.append(item)
103         self.nsNew = []
104         return newlist
105
106     def fixname(self, name):
107         if ' ' in name:
108             uri, name = name.split(' ')
109             prefix = self.nsDict[uri]
110             prefixed = name
111             if prefix:
112                 prefixed = "%s:%s" % (prefix, name)
113             ns = 'x'
114             if uri == ZOPE_TAL_NS:
115                 ns = 'tal'
116             elif uri == ZOPE_METAL_NS:
117                 ns = 'metal'
118             elif uri == ZOPE_I18N_NS:
119                 ns = 'i18n'
120             return (prefixed, name, ns)
121         return (name, name, None)
122
123     def EndElementHandler(self, name):
124         name = self.fixname(name)[0]
125         self.gen.emitEndElement(name)
126
127     def DefaultHandler(self, text):
128         self.gen.emitRawText(text)
129
130 def test():
131     import sys
132     p = TALParser()
133     file = "tests/input/test01.xml"
134     if sys.argv[1:]:
135         file = sys.argv[1]
136     p.parseFile(file)
137     program, macros = p.getCode()
138     from TALInterpreter import TALInterpreter
139     from DummyEngine import DummyEngine
140     engine = DummyEngine(macros)
141     TALInterpreter(program, macros, engine, sys.stdout, wrap=0)()
142
143 if __name__ == "__main__":
144     test()