Commit | Line | Data |
---|---|---|
c638d827 CR |
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() |