예제 #1
0
    def setAttributes(self, attributes):

        if attributes is not None and len(attributes) > 0:

            converted_attributes = []
            for name, value in list(attributes.items()):
                if isinstance(name, tuple):
                    new_name = NamespacedAttribute(*name)
                    del attributes[name]
                    attributes[new_name] = value

            self.soup.builder._replace_cdata_list_attribute_values(
                self.name, attributes)
            for name, value in list(attributes.items()):
                self.element[name] = value

            # The attributes may contain variables that need substitution.
            # Call set_up_substitutions manually.
            #
            # The Tag constructor called this method when the Tag was created,
            # but we just set/changed the attributes, so call it again.
            self.soup.builder.set_up_substitutions(self.element)
예제 #2
0
    def start(self, name, attrs, nsmap={}):
        # Make sure attrs is a mutable dict--lxml may send an immutable dictproxy.
        attrs = dict(attrs)
        nsprefix = None

        # ARRGGHH lxml 4.4.X has changes empty prefixes on namespaces to be the null string
        # and not None which all prior versions used! So remap '' prefixes to be None
        # so we can work with all lxml versions
        new_nsmap = {}
        for pfx, ns in list(nsmap.items()):
            if pfx is not None and pfx == '':
                pfx = None
            new_nsmap[pfx] = ns
        nsmap = new_nsmap

        # Fix bug in bs4 _lxml.py that ignores attributes that specify namespaces on this tag
        # Invert each namespace map as it comes in.
        if len(nsmap) > 0:

            # to make later processing easier, remap epub namespaces to use
            # epub standard prefixes
            new_nsmap = {}
            for pfx, ns in list(nsmap.items()):
                new_pfx = _standard_epub_prefix_map.get(ns, pfx)
                if new_pfx is not None and new_pfx == "opf" and pfx is None:
                    new_pfx = None
                new_nsmap[new_pfx] = ns
            nsmap = new_nsmap

            # A new namespace mapping has come into play.
            inverted_nsmap = dict(
                (value, key) for key, value in list(nsmap.items()))
            self.nsmaps.append(inverted_nsmap)

            # Also treat the namespace mapping as a set of attributes on the
            # tag, so we can properly recreate it later.
            attrs = attrs.copy()
            for prefix, namespace in list(nsmap.items()):
                attribute = NamespacedAttribute(
                    "xmlns", prefix, "http://www.w3.org/2000/xmlns/")
                attrs[attribute] = namespace

        elif len(self.nsmaps) > 1:
            # There are no new namespaces for this tag, but
            # non-default namespaces are in play, so we need a
            # separate tag stack to know when they end.
            self.nsmaps.append(None)

        # Namespaces are in play. Find any attributes that came in
        # from lxml with namespaces attached to their names, and
        # turn then into NamespacedAttribute objects.
        new_attrs = {}
        for attr, value in list(attrs.items()):
            namespace, attr = self._getNsTag(attr)
            if namespace is None:
                new_attrs[attr] = value
            else:
                nsprefix = self._prefix_for_attr_namespace(namespace)
                attr = NamespacedAttribute(nsprefix, attr, namespace)
                new_attrs[attr] = value
        attrs = new_attrs

        namespace, name = self._getNsTag(name)
        nsprefix = self._prefix_for_tag_namespace(namespace)
        self.soup.handle_starttag(name, namespace, nsprefix, attrs)