File: TemplateElement.py

package info (click to toggle)
python-xml 0.8.4-10.1%2Blenny1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 4,972 kB
  • ctags: 10,628
  • sloc: python: 46,730; ansic: 14,354; xml: 968; makefile: 201; sh: 20
file content (149 lines) | stat: -rw-r--r-- 5,536 bytes parent folder | download | duplicates (3)
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