class variable_element(xslt_element): """ Implementation of the `xsl:variable` element. """ content_model = content_model.template attribute_types = { 'name': attribute_types.qname(required=True), 'select': attribute_types.expression(), } def setup(self): # check for a bad binding if self._select and self.children: raise XsltError(XsltError.VAR_WITH_CONTENT_AND_SELECT, name=self._name) return def instantiate(self, context): # NOTE: all we want to do is change the varBindings if self._select: context.instruction = self context.namespaces = self.namespaces result = self._select.evaluate(context) elif self.children: context.push_tree_writer(self.base_uri) self.process_children(context) writer = context.pop_writer() result = writer.get_result() else: result = u"" context.variables[self._name] = result return
class key_element(xslt_element): """Implementation of the `xsl:key` element""" content_model = content_model.empty attribute_types = { 'name': attribute_types.qname(required=True), 'match': attribute_types.pattern(required=True), 'use': attribute_types.expression(required=True), }
class with_param_element(xslt_element): """ Implementation of the `xsl:with-param` element. """ content_model = content_model.template attribute_types = { 'name': attribute_types.qname(required=True), 'select': attribute_types.expression(), } def setup(self): if not self._select: self._select = rtf_expression(self) return
class result_element(xslt_element): """ When an func:result element is instantiated, during the instantiation of a func:function element, the function returns with its value. """ content_model = content_model.template attribute_types = { 'select': attribute_types.expression(), } _function = None def setup(self): if not self._select: self._select = rtf_expression(self) return def prime(self, context): current = self.parent while current: # this loop will stop when it hits the top of the tree if current.expanded_name == (EXSL_FUNCTIONS_NS, 'function'): self._function = current break current = current.parent if not self._function: raise XsltRuntimeError(XsltError.RESULT_NOT_IN_FUNCTION) if not self.isLastChild(): siblings = iter(self.parent.children) for node in siblings: if node is self: break for node in siblings: if node.expanded_name != (XSL_NAMESPACE, 'fallback'): raise XsltRuntimeError(XsltError.ILLEGAL_RESULT_SIBLINGS) return def instantiate(self, context): context.instruction, context.namespaces = self, self.namespaces self._function.result = self._select.evaluate(context) return
class apply_templates_element(xslt_element): content_model = content_model.rep( content_model.alt(content_model.qname(XSL_NAMESPACE, 'xsl:sort'), content_model.qname(XSL_NAMESPACE, 'xsl:with-param'))) attribute_types = { 'select': attribute_types.expression(), 'mode': attribute_types.qname(), } def setup(self): sort_keys = [] self._params = params = [] for child in self.children: if isinstance(child, sort_element): sort_keys.append(child) elif isinstance(child, with_param_element): params.append((child, child._name, child._select)) if sort_keys: self._select = sorted_expression(self._select, sort_keys) return def instantiate(self, context): params = {} for param, name, select in self._params: context.instruction, context.namespaces = param, param.namespaces params[name] = select.evaluate(context) if self._select: context.instruction, context.namespaces = self, self.namespaces try: nodes = self._select.evaluate_as_nodeset(context) except TypeError: raise raise XsltStaticError(XsltError.INVALID_APPLY_TEMPLATES_SELECT, self) else: nodes = context.node.xml_children # Process the selected nodes using `self._mode` context.transform.apply_templates(context, nodes, self._mode, params) return
class copy_of_element(xslt_element): content_model = content_model.empty attribute_types = { 'select': attribute_types.expression(required=True), } def instantiate(self, context): context.instruction = self context.namespaces = self.namespaces result = self._select.evaluate(context) if isinstance(result, tree.node): context.copy_node(result) elif isinstance(result, datatypes.nodeset): context.copy_nodes(result) else: context.text(datatypes.string(result)) return
class number_element(xslt_element): content_model = content_model.empty attribute_types = { 'level': attribute_types.choice(('single', 'multiple', 'any'), default='single'), 'count': attribute_types.pattern(), 'from': attribute_types.pattern(), 'value': attribute_types.expression(), 'format': attribute_types.string_avt(default='1'), 'lang': attribute_types.nmtoken_avt(), 'letter-value': attribute_types.choice_avt(('alphabetic', 'traditional'), default='traditional'), 'grouping-separator': attribute_types.char_avt(), 'grouping-size': attribute_types.number_avt(), } def setup(self): if self._level == 'single': if not self._count and not self._from: self._level = SIMPLE else: self._level = SINGLE elif self._level == 'multiple': self._level = MULTIPLE elif self._level == 'any': self._level = ANY if self._format.constant and self._lang.constant: format = self._format.evaluate_as_string(None) lang = self._lang.evaluate_as_string(None) self._formatter = numbers.formatter(lang, format) else: self._formatter = None return def instantiate(self, context): context.instruction = self context.namespaces = self.namespaces formatter = self._formatter if not formatter: format = self._format if format: format = format.evaluate_as_string(context) if not format: format = DEFAULT_FORMAT lang = self._lang if lang: lang = lang.evaluate_as_string(context) if not lang: lang = DEFAULT_LANG formatter = numbers.formatter(lang, format) letter_value = self._letter_value.evaluate_as_string(context) if self._grouping_separator and self._grouping_size: separator = self._grouping_separator.evaluate_as_string(context) grouping = int(self._grouping_size.evaluate_as_number(context)) else: separator = grouping = None # get the formatted value(s) if self._value: value = self._value.evaluate_as_number(context) # XSLT 1.0, Section 7.7, Paragraph 1 # ERROR: the number is NaN, infinite or less than 0.5 # RECOVERY: convert to string and insert into the result tree if not value.isfinite() or value < 0.5: result = datatypes.string(value) else: value = int(round(value)) result = formatter.format(value, letter_value, grouping, separator) else: node = context.node if self._level == SINGLE: value = self._single_value(context, node, self._count, self._from) if value == 0: value = None result = formatter.format(value, letter_value, separator, grouping) elif self._level == MULTIPLE: values = self._multiple_values(context, node) result = formatter.formatmany(values, letter_value, grouping, separator) elif self._level == ANY: value = self._any_value(context, node) if value == 0: value = None result = formatter.format(value, letter_value, grouping, separator) else: # 'single' without count or from attributes value = 1 prev = node.xml_preceding_sibling node_type = node.xml_type node_name = node.xml_name while prev: if prev.xml_type == node_type and \ prev.xml_name == node_name: value += 1 prev = prev.xml_preceding_sibling result = formatter.format(value, letter_value, grouping, separator) # add the resulting formatted value(s) to the result tree context.text(result) return def _single_value(self, context, node, countPattern, fromPattern): if not countPattern: if not node.xml_local: # text, comment and processing instruction countPattern = NodeTypeTest(node) else: countPattern = NameTest(node) if fromPattern: start = node.xml_parent while start and not fromPattern.match(context, start): start = start.xml_parent else: start = node.xml_root while not countPattern.match(context, node): node = node.xml_parent if node is None or node == start: return 0 value = 0 while node: value += 1 node = node.xml_preceding_sibling while node and not countPattern.match(context, node): node = node.xml_preceding_sibling return value def _multiple_values(self, context, node): count = self._count if not count: if isinstance(node, (tree.element, tree.attribute)): count = name_pattern(node.xml_type, node.xml_name) else: count = type_pattern(node.xml_type) values = [] while node: if count.match(context, node): value = self._single_value(context, node, count, None) values.insert(0, value) node = node.xml_parent if node and self._from and self._from.match(context, node): break return values def _any_value(self, context, node): count = self._count if not count: if isinstance(node, (tree.element, tree.attribute)): count = name_pattern(node.xml_type, node.xml_name) else: count = type_pattern(node.xml_type) value = 0 while node: if self._from and self._from.match(context, node): break if count.match(context, node): value += 1 next = node.xml_preceding_sibling if not next: node = node.xml_parent else: node = next next = getattr(node, 'xml_last_child', None) while next: node = next next = getattr(node, 'xml_last_child', None) return value