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
|