Code

missed one
[roundup.git] / TAL / TALParser.py
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 """
18 import string
19 from XMLParser import XMLParser
20 from TALDefs import *
21 from TALGenerator import TALGenerator
23 class TALParser(XMLParser):
25     ordered_attributes = 1
27     def __init__(self, gen=None): # Override
28         XMLParser.__init__(self)
29         if gen is None:
30             gen = TALGenerator()
31         self.gen = gen
32         self.nsStack = []
33         self.nsDict = {XML_NS: 'xml'}
34         self.nsNew = []
36     def getCode(self):
37         return self.gen.getCode()
39     def getWarnings(self):
40         return ()
42     def StartNamespaceDeclHandler(self, prefix, uri):
43         self.nsStack.append(self.nsDict.copy())
44         self.nsDict[uri] = prefix
45         self.nsNew.append((prefix, uri))
47     def EndNamespaceDeclHandler(self, prefix):
48         self.nsDict = self.nsStack.pop()
50     def StartElementHandler(self, name, attrs):
51         if self.ordered_attributes:
52             # attrs is a list of alternating names and values
53             attrlist = []
54             for i in range(0, len(attrs), 2):
55                 key = attrs[i]
56                 value = attrs[i+1]
57                 attrlist.append((key, value))
58         else:
59             # attrs is a dict of {name: value}
60             attrlist = attrs.items()
61             attrlist.sort() # For definiteness
62         name, attrlist, taldict, metaldict = self.process_ns(name, attrlist)
63         attrlist = self.xmlnsattrs() + attrlist
64         self.gen.emitStartElement(name, attrlist, taldict, metaldict)
66     def process_ns(self, name, attrlist):
67         taldict = {}
68         metaldict = {}
69         fixedattrlist = []
70         name, namebase, namens = self.fixname(name)
71         for key, value in attrlist:
72             key, keybase, keyns = self.fixname(key)
73             ns = keyns or namens # default to tag namespace
74             item = key, value
75             if ns == 'metal':
76                 metaldict[keybase] = value
77                 item = item + ("metal",)
78             elif ns == 'tal':
79                 taldict[keybase] = value
80                 item = item + ("tal",)
81             fixedattrlist.append(item)
82         if namens in ('metal', 'tal'):
83             taldict['tal tag'] = namens
84         return name, fixedattrlist, taldict, metaldict
86     def xmlnsattrs(self):
87         newlist = []
88         for prefix, uri in self.nsNew:
89             if prefix:
90                 key = "xmlns:" + prefix
91             else:
92                 key = "xmlns"
93             if uri in (ZOPE_METAL_NS, ZOPE_TAL_NS):
94                 item = (key, uri, "xmlns")
95             else:
96                 item = (key, uri)
97             newlist.append(item)
98         self.nsNew = []
99         return newlist
101     def fixname(self, name):
102         if ' ' in name:
103             uri, name = string.split(name, ' ')
104             prefix = self.nsDict[uri]
105             prefixed = name
106             if prefix:
107                 prefixed = "%s:%s" % (prefix, name)
108             ns = 'x'
109             if uri == ZOPE_TAL_NS:
110                 ns = 'tal'
111             elif uri == ZOPE_METAL_NS:
112                 ns = 'metal'
113             return (prefixed, name, ns)
114         return (name, name, None)
116     def EndElementHandler(self, name):
117         name = self.fixname(name)[0]
118         self.gen.emitEndElement(name)
120     def DefaultHandler(self, text):
121         self.gen.emitRawText(text)
123 def test():
124     import sys
125     p = TALParser()
126     file = "tests/input/test01.xml"
127     if sys.argv[1:]:
128         file = sys.argv[1]
129     p.parseFile(file)
130     program, macros = p.getCode()
131     from TALInterpreter import TALInterpreter
132     from DummyEngine import DummyEngine
133     engine = DummyEngine(macros)
134     TALInterpreter(program, macros, engine, sys.stdout, wrap=0)()
136 if __name__ == "__main__":
137     test()