Beispiel #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
Beispiel #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),
    }
Beispiel #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
Beispiel #4
0
class decimal_format_element(xslt_element):
    content_model = content_model.empty
    attribute_types = {
        'name': attribute_types.qname(),
        'decimal-separator': attribute_types.char(default='.'),
        'grouping-separator': attribute_types.char(default=','),
        'infinity': attribute_types.string(default='Infinity'),
        'minus-sign': attribute_types.char(default='-'),
        'NaN': attribute_types.string(default='NaN'),
        'percent': attribute_types.char(default='%'),
        'per-mille': attribute_types.char(default=unichr(0x2030)),
        'zero-digit': attribute_types.char(default='0'),
        'digit': attribute_types.char(default='#'),
        'pattern-separator': attribute_types.char(default=';'),
    }
Beispiel #5
0
class output_element(xslt_element):
    """Implementation of the `xsl:output` element"""
    content_model = content_model.empty
    attribute_types = {
        'method':
        attribute_types.qname(),
        'version':
        attribute_types.nmtoken(),
        'encoding':
        attribute_types.string(),
        'omit-xml-declaration':
        attribute_types.yesno(),
        'standalone':
        attribute_types.yesno(),
        'doctype-public':
        attribute_types.string(),
        'doctype-system':
        attribute_types.string(),
        'cdata-section-elements':
        attribute_types.qnames(),
        'indent':
        attribute_types.yesno(),
        'media-type':
        attribute_types.string(),
        'f:byte-order-mark':
        attribute_types.yesno(
            description=("Whether to force output of a byte order mark (BOM). "
                         "Usually used to generate a UTF-8 BOM.  Do not use "
                         "unless you're sure you know what you're doing")),
        'f:canonical-form':
        attribute_types.yesno(),
    }

    def setup(self):
        if (EXTENSION_NAMESPACE, 'byte-order-mark') in self.attributes:
            value = self.attributes[EXTENSION_NAMESPACE, 'byte-order-mark']
            self._byte_order_mark = value == 'yes'
        else:
            self._byte_order_mark = None
        if (EXTENSION_NAMESPACE, 'canonical-form') in self.attributes:
            value = self.attributes[EXTENSION_NAMESPACE, 'canonical-form']
            self._canonical_form = value == 'yes'
        else:
            self._canonical_form = None
        return
Beispiel #6
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
Beispiel #7
0
class call_template_element(xslt_element):

    content_model = content_model.rep(
        content_model.qname(XSL_NAMESPACE, 'xsl:with-param')
        )
    attribute_types = {
        'name': attribute_types.qname(required=True),
        }

    _tail_recursive = False

    def setup(self):
        self._params = [ (child, child._name, child._select)
                         for child in self.children ]
        return

    def prime(self, context,
                 _test_elements=(if_element.if_element,),
                 _choose_elements=(choose_elements.when_element,
                                   choose_elements.otherwise_element,)):
        transform = self.root.stylesheet
        try:
            template = self._template = transform.named_templates[self._name]
        except KeyError:
            raise XsltError(XsltError.NAMED_TEMPLATE_NOT_FOUND,
                            self, self._name)
        # NOTE: Tail recursion is now checked for in the xsl:template setup().
        return

    def instantiate(self, context):
        # We need to calculate the parameters before the variable context
        # is changed back in the template element
        params = {}
        for param, name, select in self._params:
            context.instruction, context.namespaces = param, param.namespaces
            params[name] = select.evaluate(context)

        if self._tail_recursive:
            context.recursive_parameters = params
        else:
            #context.current_node = context.node
            self._template.instantiate(context, params)
        return
Beispiel #8
0
class attribute_set_element(xslt_element):
    content_model = content_model.rep(
        content_model.qname(XSL_NAMESPACE, 'xsl:attribute'))
    attribute_types = {
        'name': attribute_types.qname(required=True),
        'use-attribute-sets': attribute_types.qnames(),
    }

    def instantiate(self, context, used=None):
        if used is None:
            used = []

        if self in used:
            raise XsltError(XsltError.CIRCULAR_ATTRIBUTE_SET, self, self._name)
        else:
            used.append(self)

        # XSLT 1.0, Section 7.1.4, Paragraph 4:
        # The available variable bindings are only the top-level ones.
        variables = context.variables
        context.variables = context.global_variables

        attribute_sets = context.transform.attribute_sets
        for name in self._use_attribute_sets:
            try:
                attribute_set = attribute_sets[name]
            except KeyError:
                raise XsltError(XsltError.UNDEFINED_ATTRIBUTE_SET, self,
                                attr_set_name)
            else:
                attribute_set.instantiate(context)

        self.process_children(context)

        context.variables = variables
        used.remove(self)
        return
Beispiel #9
0
class template_element(xslt_element):

    content_model = content_model.seq(
        content_model.rep(content_model.qname(XSL_NAMESPACE, 'xsl:param')),
        content_model.template,
    )
    attribute_types = {
        'match': attribute_types.pattern(),
        'name': attribute_types.qname(),
        'priority': attribute_types.number(),
        'mode': attribute_types.qname(),
    }

    _tail_recursive = False

    def __repr__(self):
        return "<template_element match='%s', name='%s', mode='%s', priority='%s'>" % (
            self._match, self._name, self._mode, self._priority)

    def setup(self):
        params = self._params = []
        for child in self.children:
            if isinstance(child, param_element):
                params.append((child, child._name))
            elif isinstance(child, xslt_element):
                break
        if self._params:
            self._instructions = self.children[len(self._params) + 1:-1]
        else:
            self._instructions = self.children
        # Check for tail-recursive invocation (i.e, call-tempates of self)
        if self._name and self._instructions:
            endpoints = [self._instructions[-1]]
            queue = endpoints.append
            for last in endpoints:
                if isinstance(last, call_template_element):
                    if last._name == self._name:
                        self._tail_recursive = True
                        last._tail_recursive = True
                        break
                elif isinstance(last, if_element):
                    last = last.last_instruction
                    if last: queue(last)
                elif isinstance(last, choose_element):
                    for choice in last.children:
                        last = choice.last_instruction
                        if last: queue(last)
        return

    def _printTemplateInfo(self):
        info, tname = self.getTemplateInfo()
        if tname:
            print "Template named %r:" % tname
        else:
            print "Template matching pattern %r :" % self._match
        print "  location: line %d, col %d of %s" % \
                (self.lineNumber, self.columnNumber, self.baseUri)
        for shortcut in info:
            print "  shortcut:"
            importidx, priority, tmode, patterninfo, quickkey = shortcut
            print "    ...import index:", importidx
            print "    .......priority:", priority
            print "    ...........mode:", tmode
            if not tname:
                print "    ......quick key: node type %s, expanded-name %r" % quickkey
                print "    ........pattern: %r  for axis type %s" % patterninfo[
                    0:2]
        return

    def instantiate(self, context, params=None):
        if params is None:
            params = {}

        if self._params:
            variables = context.variables
            context.variables = variables.copy()

        # The optimizer converts this to, roughly, a do/while loop
        while 1:
            context.recursive_parameters = None
            for child, param in self._params:
                if param in params:
                    context.variables[param] = params[param]
                else:
                    child.instantiate(context)

            for child in self._instructions:
                child.instantiate(context)

            # Update the params from the values given in
            # `recursive_parameters`.
            params = context.recursive_parameters
            if params is None:
                break

        if self._params:
            context.variables = variables
        return