Esempio n. 1
0
def writer(stream=sys.stdout, **kwargs):
    from amara.writers.outputparameters import outputparameters
    oparams = outputparameters(**kwargs)
    if kwargs.get("method", "xml") == "xml":
        from amara.writers.xmlwriter import _xmluserwriter
        writer_class = _xmluserwriter
    else:
        from amara.writers.htmlwriter import _htmluserwriter
        writer_class = _htmluserwriter
    return writer_class(oparams, stream)
Esempio n. 2
0
 def instantiate(self, context):
     output_parameters = outputparameters.outputparameters(
         method='xml', encoding=context.output_parameters.encoding,
         omit_xml_declaration=True)
     writer = xmlwriter.xmlwriter(output_parameters, StringIO())
     context.push_writer(writer)
     try:
         self.process_children(context)
     finally:
         writer = context.pop_writer()
     msg = writer.stream.getvalue()
     if self._terminate:
         raise XsltError(XsltError.STYLESHEET_REQUESTED_TERMINATION, msg=msg)
     else:
         context.message(msg)
     return
Esempio n. 3
0
 def instantiate(self, context):
     output_parameters = outputparameters.outputparameters(
         method='xml',
         encoding=context.output_parameters.encoding,
         omit_xml_declaration=True)
     writer = xmlwriter.xmlwriter(output_parameters, StringIO())
     context.push_writer(writer)
     try:
         self.process_children(context)
     finally:
         writer = context.pop_writer()
     msg = writer.stream.getvalue()
     if self._terminate:
         raise XsltError(XsltError.STYLESHEET_REQUESTED_TERMINATION,
                         msg=msg)
     else:
         context.message(msg)
     return
Esempio n. 4
0
    def setup(self, _param_element=variable_elements.param_element):
        """
        Called only once, at the first initialization
        """
        self.output_parameters = outputparameters.outputparameters()

        # Sort the top-level elements in decreasing import precedence to ease
        # processing later.
        precedence_key = operator.attrgetter('import_precedence')
        elements = sorted(self.children, key=precedence_key, reverse=True)

        # Merge the top-level stylesheet elements into their respective
        # lists.  Any element name not in the mapping is discarded.
        # Note, by sharing the same list no merging is required later.
        whitespace_elements, variable_elements = [], []
        top_level_elements = {
            'strip-space' : whitespace_elements,
            'preserve-space' : whitespace_elements,
            'output' : [],
            'key' : [],
            'decimal-format' : [],
            'namespace-alias' : [],
            'attribute-set': [],
            'variable' : variable_elements,
            'param' : variable_elements,
            'template' : [],
            }
        # Using `groupby` takes advantage of series of same-named elements
        # appearing adjacent to each other.
        key = operator.attrgetter('expanded_name')
        for (namespace, name), nodes in itertools.groupby(self.children, key):
            if namespace == XSL_NAMESPACE and name in top_level_elements:
                top_level_elements[name].extend(nodes)

        # - process the `xsl:preserve-space` and `xsl:strip-space` elements
        # RECOVERY: Multiple matching patterns use the last occurance
        space_rules = {}
        for element in whitespace_elements:
            strip = element._strip_whitespace
            for token in element._elements:
                namespace, name = token
                space_rules[token] = (namespace, name, strip)
        self.space_rules = space_rules.values()
        # sort in decreasing priority, where `*` is lowest, followed by
        # `prefix:*`, then all others.
        self.space_rules.sort(reverse=True)

        # - process the `xsl:output` elements
        # Sort in increasing import precedence, so the last one added
        # will have the highest import precedence
        elements = top_level_elements['output']
        getter = operator.attrgetter(
            '_method', '_version', '_encoding', '_omit_xml_declaration',
            '_standalone', '_doctype_system', '_doctype_public',
            '_cdata_section_elements', '_indent', '_media_type',
            '_byte_order_mark', '_canonical_form')
        for element in elements:
            (method, version, encoding, omit_xmldecl, standalone,
             doctype_system, doctype_public, cdata_elements, indent,
             media_type, byte_order_mark, canonical_form) = getter(element)
            if method is not None:
                self.output_parameters.method = method
            if version is not None:
                self.output_parameters.version = version
            if encoding is not None:
                self.output_parameters.encoding = encoding
            if omit_xmldecl is not None:
                self.output_parameters.omit_xml_declaration = omit_xmldecl
            if standalone is not None:
                self.output_parameters.standalone = standalone
            if doctype_system is not None:
                self.output_parameters.doctype_system = doctype_system
            if doctype_public is not None:
                self.output_parameters.doctype_public = doctype_public
            if cdata_elements:
                self.output_parameters.cdata_section_elements += cdata_elements
            if indent is not None:
                self.output_parameters.indent = indent
            if media_type is not None:
                self.output_parameters.media_type = media_type
            if byte_order_mark is not None:
                self.output_parameters.byte_order_mark = byte_order_mark
            if canonical_form is not None:
                self.output_parameters.canonical_form = canonical_form

        # - process the `xsl:key` elements
        # Group the keys by name
        elements = top_level_elements['key']
        name_key = operator.attrgetter('_name')
        elements.sort(key=name_key)
        keys = self._keys = {}
        for name, elements in itertools.groupby(elements, name_key):
            keys[name] = tuple(elements)

        # - process the `xsl:decimal-format` elements
        formats = self.decimal_formats = {}
        getter = operator.attrgetter(
            '_decimal_separator', '_grouping_separator', '_infinity',
            '_minus_sign', '_NaN', '_percent', '_per_mille', '_zero_digit',
            '_digit', '_pattern_separator')
        for element in top_level_elements['decimal-format']:
            name = element._name
            format = getter(element)
            # It is an error to declare a decimal-format more than once
            # (even with different import precedence) with different values.
            if name in formats and formats[name] != format:
                # Construct a useful name for the error message.
                if name:
                    namespace, name = name
                    if namespace:
                        name = element.namespaces[namespace] + ':' + name
                else:
                    name = '#default'
                raise XsltError(XsltError.DUPLICATE_DECIMAL_FORMAT, name)
            else:
              formats[name] = format
        # Add the default decimal format, if not declared.
        if None not in formats:
            formats[None] = ('.', ',', 'Infinity', '-', 'NaN', '%',
                             unichr(0x2030), '0', '#', ';')

        # - process the `xsl:namespace-alias` elements
        elements = top_level_elements['namespace-alias']
        elements.reverse()
        aliases = self.namespace_aliases = {}
        for precedence, group in itertools.groupby(elements, precedence_key):
            mapped = {}
            for element in group:
                namespace = element.namespaces[element._stylesheet_prefix]
                if namespace not in aliases:
                    mapped[namespace] = True
                    result_prefix = element._result_prefix
                    result_namespace = element.namespaces[result_prefix]
                    aliases[namespace] = (result_namespace, result_prefix)
                # It is an error for a namespace URI to be mapped to multiple
                # different namespace URIs (with the same import precedence).
                elif namespace in mapped:
                    raise XsltError(XsltError.DUPLICATE_NAMESPACE_ALIAS,
                                    element._stylesheet_prefix)
        if aliases:
            # apply namespace fixup for the literal elements
            _fixup_aliases(self, aliases)

        # - process the `xsl:attribute-set` elements
        sets = self.attribute_sets = {}
        for element in top_level_elements['attribute-set']:
            sets[element._name] = element

        # - process the `xsl:param` and `xsl:variable` elements
        index, self._variables = {}, variable_elements[:]
        variable_elements.reverse()
        for element in variable_elements:
            name = element._name
            if name not in index:
                # unique (or first) variable binding
                index[name] = 1
            else:
                # shadowed variable binding, remove from processing list
                self._variables.remove(element)
        self.parameters = frozenset(element._name for element in self._variables
                                    if isinstance(element, _param_element))

        # - process the `xsl:template` elements
        match_templates = collections.defaultdict(_type_dispatch_table)
        named_templates = self.named_templates = {}
        elements = top_level_elements['template']
        elements.reverse()
        getter = operator.attrgetter('node_test', 'axis_type', 'node_type')
        for position, element in enumerate(elements):
            match, name = element._match, element._name
            precedence = element.import_precedence
            if match:
                namespaces = element.namespaces
                template_priority = element._priority
                mode_table = match_templates[element._mode]
                for pattern in match:
                    node_test, axis_type, node_type = getter(pattern)
                    if template_priority is None:
                        priority = node_test.priority
                    else:
                        priority = template_priority
                    sort_key = (precedence, priority, position)
                    info = (sort_key, node_test, axis_type, element)
                    # Add the template rule to the dispatch table
                    type_key = node_type.xml_typecode
                    if type_key == tree.element.xml_typecode:
                        # Element types are further keyed by the name test.
                        name_key = node_test.name_key
                        if name_key:
                            prefix, local = name_key
                            # Unprefixed names are in the null-namespace
                            try:
                                namespace = prefix and namespaces[prefix]
                            except KeyError:
                                raise XPathError(XPathError.UNDEFINED_PREFIX,
                                                 prefix=prefix)
                            else:
                                name_key = namespace, local
                        mode_table[type_key][name_key].append(info)
                    else:
                        # Every other node type gets lumped into a single list
                        # for that node type
                        mode_table[type_key].append(info)
            if name:
                # XSLT 1.0, Section 6, Paragraph 3:
                # It is an error if a stylesheet contains more than one
                # template with the same name and same import precedence.
                if name not in named_templates:
                    named_templates[name] = element
                elif named_templates[name].import_precedence == precedence:
                    # Construct a useful name for the error message.
                    namespace, name = name
                    if namespace:
                        name = element.namespaces[namespace] + ':' + name
                    raise XsltError(XsltError.DUPLICATE_NAMED_TEMPLATE, name)
        # Now expanded the tables and convert to regular dictionaries to
        # prevent inadvertant growth when non-existant keys are used.
        match_templates = self.match_templates = dict(match_templates)
        for mode, type_table in match_templates.iteritems():
            # Add those patterns that don't have a distinct type:
            #   node(), id() and key() patterns
            any_patterns = type_table[tree.node.xml_typecode]
            type_table = match_templates[mode] = dict(type_table)
            for type_key, patterns in type_table.iteritems():
                if type_key == tree.element.xml_typecode:
                    # Add those that are wildcard tests ('*' and 'prefix:*')
                    wildcard_names = patterns[None]
                    name_table = type_table[type_key] = dict(patterns)
                    for name_key, patterns in name_table.iteritems():
                        if name_key is not None:
                            patterns.extend(wildcard_names)
                        patterns.extend(any_patterns)
                        patterns.sort(reverse=True)
                        name_table[name_key] = tuple(patterns)
                else:
                    patterns.extend(any_patterns)
                    patterns.sort(reverse=True)
                    type_table[type_key] = tuple(patterns)
        #self._dump_match_templates(match_templates)
        return
Esempio n. 5
0
    def setup(self, _param_element=variable_elements.param_element):
        """
        Called only once, at the first initialization
        """
        self.output_parameters = outputparameters.outputparameters()

        # Sort the top-level elements in decreasing import precedence to ease
        # processing later.
        precedence_key = operator.attrgetter('import_precedence')
        elements = sorted(self.children, key=precedence_key, reverse=True)

        # Merge the top-level stylesheet elements into their respective
        # lists.  Any element name not in the mapping is discarded.
        # Note, by sharing the same list no merging is required later.
        whitespace_elements, variable_elements = [], []
        top_level_elements = {
            'strip-space': whitespace_elements,
            'preserve-space': whitespace_elements,
            'output': [],
            'key': [],
            'decimal-format': [],
            'namespace-alias': [],
            'attribute-set': [],
            'variable': variable_elements,
            'param': variable_elements,
            'template': [],
        }
        # Using `groupby` takes advantage of series of same-named elements
        # appearing adjacent to each other.
        key = operator.attrgetter('expanded_name')
        for (namespace, name), nodes in itertools.groupby(self.children, key):
            if namespace == XSL_NAMESPACE and name in top_level_elements:
                top_level_elements[name].extend(nodes)

        # - process the `xsl:preserve-space` and `xsl:strip-space` elements
        # RECOVERY: Multiple matching patterns use the last occurance
        space_rules = {}
        for element in whitespace_elements:
            strip = element._strip_whitespace
            for token in element._elements:
                namespace, name = token
                space_rules[token] = (namespace, name, strip)
        self.space_rules = space_rules.values()
        # sort in decreasing priority, where `*` is lowest, followed by
        # `prefix:*`, then all others.
        self.space_rules.sort(reverse=True)

        # - process the `xsl:output` elements
        # Sort in increasing import precedence, so the last one added
        # will have the highest import precedence
        elements = top_level_elements['output']
        getter = operator.attrgetter('_method', '_version', '_encoding',
                                     '_omit_xml_declaration', '_standalone',
                                     '_doctype_system', '_doctype_public',
                                     '_cdata_section_elements', '_indent',
                                     '_media_type', '_byte_order_mark',
                                     '_canonical_form')
        for element in elements:
            (method, version, encoding, omit_xmldecl, standalone,
             doctype_system, doctype_public, cdata_elements, indent,
             media_type, byte_order_mark, canonical_form) = getter(element)
            if method is not None:
                self.output_parameters.method = method
            if version is not None:
                self.output_parameters.version = version
            if encoding is not None:
                self.output_parameters.encoding = encoding
            if omit_xmldecl is not None:
                self.output_parameters.omit_xml_declaration = omit_xmldecl
            if standalone is not None:
                self.output_parameters.standalone = standalone
            if doctype_system is not None:
                self.output_parameters.doctype_system = doctype_system
            if doctype_public is not None:
                self.output_parameters.doctype_public = doctype_public
            if cdata_elements:
                self.output_parameters.cdata_section_elements += cdata_elements
            if indent is not None:
                self.output_parameters.indent = indent
            if media_type is not None:
                self.output_parameters.media_type = media_type
            if byte_order_mark is not None:
                self.output_parameters.byte_order_mark = byte_order_mark
            if canonical_form is not None:
                self.output_parameters.canonical_form = canonical_form

        # - process the `xsl:key` elements
        # Group the keys by name
        elements = top_level_elements['key']
        name_key = operator.attrgetter('_name')
        elements.sort(key=name_key)
        keys = self._keys = {}
        for name, elements in itertools.groupby(elements, name_key):
            keys[name] = tuple(elements)

        # - process the `xsl:decimal-format` elements
        formats = self.decimal_formats = {}
        getter = operator.attrgetter('_decimal_separator',
                                     '_grouping_separator', '_infinity',
                                     '_minus_sign', '_NaN', '_percent',
                                     '_per_mille', '_zero_digit', '_digit',
                                     '_pattern_separator')
        for element in top_level_elements['decimal-format']:
            name = element._name
            format = getter(element)
            # It is an error to declare a decimal-format more than once
            # (even with different import precedence) with different values.
            if name in formats and formats[name] != format:
                # Construct a useful name for the error message.
                if name:
                    namespace, name = name
                    if namespace:
                        name = element.namespaces[namespace] + ':' + name
                else:
                    name = '#default'
                raise XsltError(XsltError.DUPLICATE_DECIMAL_FORMAT, name)
            else:
                formats[name] = format
        # Add the default decimal format, if not declared.
        if None not in formats:
            formats[None] = ('.', ',', 'Infinity', '-', 'NaN', '%',
                             unichr(0x2030), '0', '#', ';')

        # - process the `xsl:namespace-alias` elements
        elements = top_level_elements['namespace-alias']
        elements.reverse()
        aliases = self.namespace_aliases = {}
        for precedence, group in itertools.groupby(elements, precedence_key):
            mapped = {}
            for element in group:
                namespace = element.namespaces[element._stylesheet_prefix]
                if namespace not in aliases:
                    mapped[namespace] = True
                    result_prefix = element._result_prefix
                    result_namespace = element.namespaces[result_prefix]
                    aliases[namespace] = (result_namespace, result_prefix)
                # It is an error for a namespace URI to be mapped to multiple
                # different namespace URIs (with the same import precedence).
                elif namespace in mapped:
                    raise XsltError(XsltError.DUPLICATE_NAMESPACE_ALIAS,
                                    element._stylesheet_prefix)
        if aliases:
            # apply namespace fixup for the literal elements
            _fixup_aliases(self, aliases)

        # - process the `xsl:attribute-set` elements
        sets = self.attribute_sets = {}
        for element in top_level_elements['attribute-set']:
            sets[element._name] = element

        # - process the `xsl:param` and `xsl:variable` elements
        index, self._variables = {}, variable_elements[:]
        variable_elements.reverse()
        for element in variable_elements:
            name = element._name
            if name not in index:
                # unique (or first) variable binding
                index[name] = 1
            else:
                # shadowed variable binding, remove from processing list
                self._variables.remove(element)
        self.parameters = frozenset(element._name
                                    for element in self._variables
                                    if isinstance(element, _param_element))

        # - process the `xsl:template` elements
        match_templates = collections.defaultdict(_type_dispatch_table)
        named_templates = self.named_templates = {}
        elements = top_level_elements['template']
        elements.reverse()
        getter = operator.attrgetter('node_test', 'axis_type', 'node_type')
        for position, element in enumerate(elements):
            match, name = element._match, element._name
            precedence = element.import_precedence
            if match:
                namespaces = element.namespaces
                template_priority = element._priority
                mode_table = match_templates[element._mode]
                for pattern in match:
                    node_test, axis_type, node_type = getter(pattern)
                    if template_priority is None:
                        priority = node_test.priority
                    else:
                        priority = template_priority
                    sort_key = (precedence, priority, position)
                    info = (sort_key, node_test, axis_type, element)
                    # Add the template rule to the dispatch table
                    type_key = node_type.xml_typecode
                    if type_key == tree.element.xml_typecode:
                        # Element types are further keyed by the name test.
                        name_key = node_test.name_key
                        if name_key:
                            prefix, local = name_key
                            # Unprefixed names are in the null-namespace
                            try:
                                namespace = prefix and namespaces[prefix]
                            except KeyError:
                                raise XPathError(XPathError.UNDEFINED_PREFIX,
                                                 prefix=prefix)
                            else:
                                name_key = namespace, local
                        mode_table[type_key][name_key].append(info)
                    else:
                        # Every other node type gets lumped into a single list
                        # for that node type
                        mode_table[type_key].append(info)
            if name:
                # XSLT 1.0, Section 6, Paragraph 3:
                # It is an error if a stylesheet contains more than one
                # template with the same name and same import precedence.
                if name not in named_templates:
                    named_templates[name] = element
                elif named_templates[name].import_precedence == precedence:
                    # Construct a useful name for the error message.
                    namespace, name = name
                    if namespace:
                        name = element.namespaces[namespace] + ':' + name
                    raise XsltError(XsltError.DUPLICATE_NAMED_TEMPLATE, name)
        # Now expanded the tables and convert to regular dictionaries to
        # prevent inadvertant growth when non-existant keys are used.
        match_templates = self.match_templates = dict(match_templates)
        for mode, type_table in match_templates.iteritems():
            # Add those patterns that don't have a distinct type:
            #   node(), id() and key() patterns
            any_patterns = type_table[tree.node.xml_typecode]
            type_table = match_templates[mode] = dict(type_table)
            for type_key, patterns in type_table.iteritems():
                if type_key == tree.element.xml_typecode:
                    # Add those that are wildcard tests ('*' and 'prefix:*')
                    wildcard_names = patterns[None]
                    name_table = type_table[type_key] = dict(patterns)
                    for name_key, patterns in name_table.iteritems():
                        if name_key is not None:
                            patterns.extend(wildcard_names)
                        patterns.extend(any_patterns)
                        patterns.sort(reverse=True)
                        name_table[name_key] = tuple(patterns)
                else:
                    patterns.extend(any_patterns)
                    patterns.sort(reverse=True)
                    type_table[type_key] = tuple(patterns)
        #self._dump_match_templates(match_templates)
        return
Esempio n. 6
0
 def setup(self):
     self._output_parameters = outputparameters.outputparameters()
     return
Esempio n. 7
0
 def setup(self):
     self._output_parameters = outputparameters.outputparameters()
     return