Esempio n. 1
0
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
Esempio n. 2
0
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),
    }
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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
Esempio n. 7
0
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