1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
########################################################################
#
# File Name: TemplateElement.py
#
#
"""
Implementation of the XSLT Spec template stylesheet element.
WWW: http://4suite.com/4XSLT e-mail: support@4suite.com
Copyright (c) 1999-2000 Fourthought Inc, USA. All Rights Reserved.
See http://4suite.com/COPYRIGHT for license and copyright information
"""
import re, string
from xml.dom import EMPTY_NAMESPACE
import xml.dom.ext
import xml.dom.Element
import xml.xslt
from xml.xpath.Util import ExpandQName
from xml.xslt import XsltElement, XsltException, XPatternParser, Error, XSL_NAMESPACE
from xml.xpath import Util
#FIXME: We don't handle the priority rules rightly for templates with matches of the form a|b|c. see spec 5.5
class TemplateElement(XsltElement):
legalAttrs = ('match', 'mode', 'priority', 'name')
def __init__(self, doc, uri=xml.xslt.XSL_NAMESPACE, localName='template', prefix='xsl', baseUri=''):
XsltElement.__init__(self, doc, uri, localName, prefix, baseUri)
def setup(self):
self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self)
self.__dict__['_match'] = self.getAttributeNS(EMPTY_NAMESPACE, 'match')
mode_attr = self.getAttributeNS(EMPTY_NAMESPACE, 'mode')
if not mode_attr:
self.__dict__['_mode'] = None
else:
split_name = Util.ExpandQName(
mode_attr,
namespaces=self._nss
)
self.__dict__['_mode'] = split_name
name_attr = self.getAttributeNS(EMPTY_NAMESPACE, 'name')
split_name = Util.ExpandQName(
name_attr,
namespaces=self._nss
)
self.__dict__['_name'] = split_name
self.__dict__['_params'] = []
self.__dict__['_elements'] = []
for child in self.childNodes:
if child.namespaceURI == XSL_NAMESPACE:
if child.localName == 'param':
self.__dict__['_params'].append(child)
elif child.localName in ['choose', 'if']:
self.__dict__['_elements'].append((1, child))
else:
self.__dict__['_elements'].append((0, child))
else:
self.__dict__['_elements'].append((0, child))
#A list of tuples
#(pattern,qmatch,priority)
#either pattern or qmatch will be present but not both
self.__dict__['_patternInfo'] = []
if self._match:
priority = self.getAttributeNS(EMPTY_NAMESPACE, 'priority') or None
if priority is not None:
try:
priority = float(priority)
except:
raise XsltException(Error.ILLEGAL_TEMPLATE_PRIORITY)
parser = XPatternParser.XPatternParser()
shortcuts = parser.parsePattern(self._match).getMatchShortcuts()
for pattern, (shortcut, extra_arg) in shortcuts:
if priority is None:
tpl_priority = pattern.priority
else:
tpl_priority = priority
self.__dict__['_patternInfo'].append((shortcut,
extra_arg,
tpl_priority))
def getMatchInfo(self):
return (self._patternInfo,self._mode,self._nss)
def instantiate(self, context, processor, params=None, new_level=1):
params = params or {}
#NOTE Don't reset the context
context.setNamespaces(self._nss)
origVars = context.varBindings.copy()
# Set the parameter list
for param in self._params:
value = params.get(param._name)
if value is not None:
context.varBindings[param._name] = value
else:
context = param.instantiate(context, processor)[0]
rec_tpl_params = None
for (recurse,child) in self._elements:
if recurse:
context, rec_tpl_params = child.instantiate(context,
processor,
new_level)
else:
context = child.instantiate(context, processor)[0]
context.varBindings = origVars
return (context, rec_tpl_params)
def __getinitargs__(self):
return (None, self.namespaceURI, self.localName, self.prefix,
self.baseUri)
def __getstate__(self):
base_state = XsltElement.__getstate__(self)
new_state = (base_state, self._nss, self._name, self._mode,
self._patternInfo, self._match, self._params,
self._elements)
return new_state
def __setstate__(self, state):
XsltElement.__setstate__(self, state[0])
self._nss = state[1]
self._name = state[2]
self._mode = state[3]
self._patternInfo = state[4]
self._match = state[5]
self._params = state[6]
self._elements = state[7]
return
def mergeUnbalancedPipes(self, patterns):
ctr = 0
while ctr < len(patterns)-1:
if string.count(patterns[ctr],'[') != string.count(patterns[ctr], ']'):
patterns[ctr] = patterns[ctr] + '|' +patterns[ctr+1]
else:
ctr = ctr + 1
patterns = map(lambda x:string.strip(x), patterns)
return patterns
|