Esempio n. 1
0
def variable_element(tagname, namespaces, attributes):
    # required `name` attribute
    try:
        name = attributes[None, 'name']
    except KeyError:
        raise XUpdateError(XUpdateError.MISSING_REQUIRED_ATTRIBUTE,
                           element=tagname, attribute='name')
    else:
        if not isqname(name):
            raise XUpdateError(XUpdateError.INVALID_QNAME_ATTR,
                               attribute='name', value=name)
        prefix, name = splitqname(name)
        if prefix:
            try:
                namespace = namespaces[prefix]
            except KeyError:
                raise XUpdateError(XUpdateError.UNDEFINED_PREFIX,
                                   prefix=prefix)
        else:
            namespace = None
        name = (namespace, name)
    # optional `select` attribute
    if (None, 'select') in attributes:
        select = attributes[None, 'select']
        try:
            select = parse_expression(select)
        except XPathError, error:
            raise XUpdateError(XUpdateError.SYNTAX_ERROR,
                               expression=select, text=str(error))
Esempio n. 2
0
    def start_element(self,
                      name,
                      namespace=None,
                      namespaces=None,
                      attributes=None):
        """
        attributes must be a mapping from (name, namespace) to value.  namespace can be None
        """
        self._complete_element()

        if self._need_doctype:
            self._printer.doctype(name, self.output_parameters.doctype_public,
                                  self.output_parameters.doctype_system)
            self._need_doctype = False

        self._element_name = name
        self._element_namespace = namespace
        prefix, local = xmlstring.splitqname(name)

        # Update in-scope namespaces
        inscope_namespaces = self._namespaces[-1].copy()
        if namespaces:
            inscope_namespaces.update(namespaces)
        inscope_namespaces[prefix] = namespace
        self._namespaces.append(inscope_namespaces)
        if attributes:
            for (name, namespace), value in attributes.iteritems():
                self.attribute(name, value, namespace)
        return
Esempio n. 3
0
    def instantiate(self, context):
        context.push_string_writer(errors=False)
        for primitive in self:
            primitive.instantiate(context)
        writer = context.pop_writer()
        name = writer.get_result()
        prefix, local = splitqname(name)
        if prefix:
            namespace = self.namespaces[prefix]
        else:
            namespace = None

        context.namespaces = self.namespaces
        targets = self.select.evaluate_as_nodeset(context)
        if not targets:
            raise XUpdateError(XUpdateError.INVALID_SELECT)
        for target in targets:
            parent = target.xml_parent
            if target.xml_type == tree.attribute.xml_type:
                parent.xml_attributes[namespace, name] = target.xml_value
            elif target.xml_type == tree.processing_instruction.xml_type:
                pi = tree.processing_instruction(name, target.xml_data)
                parent.xml_replace-child(pi, target)
            elif target.xml_type == tree.element.xml_type:
                #FIXME: Use regular constructor. No more DOM factory
                element = tree.element(namespace, name)
                # Copy any existing attributes to the newly created element
                if target.xml_attributes:
                    for (ns, qname), value in target.xml_attributes.iteritems():
                        element.xml_attributes[ns, qname] = value
                # Now copy any children as well
                while target.xml_first_child:
                    element.xml_append(target.xml_first_child)
                parent.xml_replace(target, element)
        return
Esempio n. 4
0
    def start_element(self, name, namespace=None, namespaces=None,
                      attributes=None):
        """
        attributes must be a mapping from (name, namespace) to value.  namespace can be None
        """
        self._complete_element()

        if self._need_doctype:
            self._printer.doctype(name,
                                    self.output_parameters.doctype_public,
                                    self.output_parameters.doctype_system)
            self._need_doctype = False

        self._element_name = name
        self._element_namespace = namespace
        prefix, local = xmlstring.splitqname(name)

        # Update in-scope namespaces
        inscope_namespaces = self._namespaces[-1].copy()
        if namespaces:
            inscope_namespaces.update(namespaces)
        inscope_namespaces[prefix] = namespace
        self._namespaces.append(inscope_namespaces)
        if attributes:
            for (name, namespace), value in attributes.iteritems():
                self.attribute(name, value, namespace)
        return
Esempio n. 5
0
def variable_element(tagname, namespaces, attributes):
    # required `name` attribute
    try:
        name = attributes[None, 'name']
    except KeyError:
        raise XUpdateError(XUpdateError.MISSING_REQUIRED_ATTRIBUTE,
                           element=tagname,
                           attribute='name')
    else:
        if not isqname(name):
            raise XUpdateError(XUpdateError.INVALID_QNAME_ATTR,
                               attribute='name',
                               value=name)
        prefix, name = splitqname(name)
        if prefix:
            try:
                namespace = namespaces[prefix]
            except KeyError:
                raise XUpdateError(XUpdateError.UNDEFINED_PREFIX,
                                   prefix=prefix)
        else:
            namespace = None
        name = (namespace, name)
    # optional `select` attribute
    if (None, 'select') in attributes:
        select = attributes[None, 'select']
        try:
            select = parse_expression(select)
        except XPathError, error:
            raise XUpdateError(XUpdateError.SYNTAX_ERROR,
                               expression=select,
                               text=str(error))
Esempio n. 6
0
 def prepare(self, element, value):
     if value is None:
         if self.default is None:
             return None
         value = self.default
     elif not isqname(value):
         raise XsltError(XsltError.INVALID_QNAME_ATTR, value=value)
     return splitqname(value)
Esempio n. 7
0
 def instantiate(self, context):
     context.namespaces = self.namespaces
     name = self.name.evaluate_as_string(context)
     if self.namespace:
         namespace = self.namespace.evaluate_as_string(context)
     else:
         prefix, local = splitqname(name)
         try:
             namespace = self.namespaces[prefix]
         except KeyError:
             if not prefix:
                 prefix = '#default'
             raise XUpdateError(XUpdateError.UNDEFINED_PREFIX,
                                prefix=prefix)
     context.start_element(name, namespace)
     for child in self:
         child.instantiate(context)
     context.end_element(name, namespace)
     return
Esempio n. 8
0
 def instantiate(self, context):
     context.namespaces = self.namespaces
     name = self.name.evaluate_as_string(context)
     if self.namespace:
         namespace = self.namespace.evaluate_as_string(context)
     else:
         prefix, local = splitqname(name)
         try:
             namespace = self.namespaces[prefix]
         except KeyError:
             if not prefix:
                 prefix = '#default'
             raise XUpdateError(XUpdateError.UNDEFINED_PREFIX,
                                prefix=prefix)
     context.start_element(name, namespace)
     for child in self:
         child.instantiate(context)
     context.end_element(name, namespace)
     return
Esempio n. 9
0
    def prepare(self, element, value):
        if value is None:
            if self.default is None:
                return None
            value = self.default
        elif not isqname(value):
            raise XsltError(XsltError.INVALID_QNAME_ATTR, value=value)

        prefix, local = splitqname(value)
        if prefix:
            try:
                namespace = element.namespaces[prefix]
            except KeyError:
                raise XsltRuntimeException(XsltError.UNDEFINED_PREFIX,
                                           elem=element,
                                           prefix=prefix)
        else:
            namespace = None
        return (namespace, local)
Esempio n. 10
0
 def instantiate(self, context):
     context.namespaces = self.namespaces
     name = self.name.evaluate_as_string(context)
     if self.namespace:
         namespace = self.namespace.evaluate_as_string(context)
     else:
         prefix, local = splitqname(name)
         if prefix:
             try:
                 namespace = self.namespaces[prefix]
             except KeyError:
                 raise XUpdateError(XUpdateError.UNDEFINED_PREFIX,
                                 prefix=prefix)
         else:
             namespace = None
     context.push_string_writer(errors=False)
     for child in self:
         child.instantiate(context)
     writer = context.pop_writer()
     context.attribute(name, writer.get_result(), namespace)
     return
Esempio n. 11
0
 def instantiate(self, context):
     context.namespaces = self.namespaces
     name = self.name.evaluate_as_string(context)
     if self.namespace:
         namespace = self.namespace.evaluate_as_string(context)
     else:
         prefix, local = splitqname(name)
         if prefix:
             try:
                 namespace = self.namespaces[prefix]
             except KeyError:
                 raise XUpdateError(XUpdateError.UNDEFINED_PREFIX,
                                    prefix=prefix)
         else:
             namespace = None
     context.push_string_writer(errors=False)
     for child in self:
         child.instantiate(context)
     writer = context.pop_writer()
     context.attribute(name, writer.get_result(), namespace)
     return
Esempio n. 12
0
    def attribute(self, name, value, namespace=None):
        """
        add an attribute to an element

        name - the qualified name of the attribute
        value - the attribute value: must be Unicode
        namespace - must be Unicode or None (the default)

        Strives for "sanity".  For brilliant definition thereof, c.f. Joe English
        http://lists.xml.org/archives/xml-dev/200204/msg00170.html
        Uses terminology from that article
        See also discussions starting
        http://lists.fourthought.com/pipermail/4suite-dev/2003-March/001294.html
        http://lists.fourthought.com/pipermail/4suite-dev/2003-March/001283.html

        Note: attribute output is computed as invoked.
        This means that the ugly case

        attribute(u"foo", u"bar", "http://some-ns/")
        attribute(u"x:foo", u"baz", "http://some-ns/")

        will result in the ugly
          xmlns:org.4suite.4xslt.ns0="http://some-ns/"
          org.4suite.4xslt.ns0:foo="baz"

        The user can easily correct this by reversing the
        order of the calls
        """
        if not self._element_name:
            if self._need_doctype:
                raise WriterError(WriterError.ATTRIBUTE_ADDED_TO_NON_ELEMENT)
            else:
                raise WriterError(WriterError.ATTRIBUTE_ADDED_TOO_LATE)
        prefix, local = xmlstring.splitqname(name)
        if namespace is None:
            name = local
        else:
            # The general approach is as follows:
            # - If the new namespace/prefix combo is unique in the scope, add
            #   it as is.
            #
            # - If the prefix is new, but the namespace already present, avoid
            #   psychosis by reusing the existing namespace (even if it means
            #   putting a formerly prefixed node into defaulted namespace form).
            #   Note that this can cause effective non-conformance in some cases
            #   because the XSLT spec says that all namespace nodes must be
            #   copied to the reslt tree (even if this causes psychosis).
            #   There is no mandate that all ns nodes must be manifestd as
            #   matching NS Decls in the serialization, but if the output is
            #   to result tree fragment, the required ns nodes will simply
            #   disappear.
            #
            # - If the prefix exists, but with a different namespace, generate
            #   a new (and probably rather ugly) prefix.
            namespaces = self._namespaces[-1]
            if not prefix or prefix == 'xmlns':
                # Find an existing namespace/prefix pair
                for prefix, inscope_namespace in namespaces.iteritems():
                    if prefix and inscope_namespace == namespace:
                        break
                else:
                    # Generate a new prefix
                    template = self.GENERATED_PREFIX
                    for suffix in itertools.count():
                        prefix = template % suffix
                        if prefix not in namespaces:
                            break
                    namespaces[prefix] = namespace
            elif prefix not in namespaces:
                # Find an existing namespace/prefix pair
                for inscope_prefix, inscope_namespace in namespaces.iteritems(
                ):
                    if inscope_prefix and inscope_namespace == namespace:
                        prefix = inscope_prefix
                        break
                else:
                    # Use given namespace/prefix pair
                    namespaces[prefix] = namespace
            elif namespaces[prefix] != namespace:
                # An existing prefix/namespace pair that doesn't match what
                # we're trying to use. First, try to reuse an existing namespace
                # declaration.
                for prefix, inscope_namespace in namespaces.iteritems():
                    if prefix and inscope_namespace == namespace:
                        break
                else:
                    # Generate a new prefix
                    template = self.GENERATED_PREFIX
                    for suffix in itertools.count():
                        prefix = template % suffix
                        if prefix not in namespaces:
                            break
                    namespaces[prefix] = namespace
            # Generate a new node name
            assert prefix, "'prefix' required for non-null namespace"
            name = prefix + ':' + local

        self._attributes[namespace, local] = (name, value)
        return
Esempio n. 13
0
def qname_type(namespace, name):
    prefix, local = splitqname(name)
    return ContentModel(ContentModel.TYPE_NAME, (namespace, local), label=name)
Esempio n. 14
0
    def attribute(self, name, value, namespace=None):
        """
        add an attribute to an element

        name - the qualified name of the attribute
        value - the attribute value: must be Unicode
        namespace - must be Unicode or None (the default)

        Strives for "sanity".  For brilliant definition thereof, c.f. Joe English
        http://lists.xml.org/archives/xml-dev/200204/msg00170.html
        Uses terminology from that article
        See also discussions starting
        http://lists.fourthought.com/pipermail/4suite-dev/2003-March/001294.html
        http://lists.fourthought.com/pipermail/4suite-dev/2003-March/001283.html

        Note: attribute output is computed as invoked.
        This means that the ugly case

        attribute(u"foo", u"bar", "http://some-ns/")
        attribute(u"x:foo", u"baz", "http://some-ns/")

        will result in the ugly
          xmlns:org.4suite.4xslt.ns0="http://some-ns/"
          org.4suite.4xslt.ns0:foo="baz"

        The user can easily correct this by reversing the
        order of the calls
        """
        if not self._element_name:
            if self._need_doctype:
                raise WriterError(WriterError.ATTRIBUTE_ADDED_TO_NON_ELEMENT)
            else:
                raise WriterError(WriterError.ATTRIBUTE_ADDED_TOO_LATE)
        prefix, local = xmlstring.splitqname(name)
        if namespace is None:
            name = local
        else:
            # The general approach is as follows:
            # - If the new namespace/prefix combo is unique in the scope, add
            #   it as is.
            #
            # - If the prefix is new, but the namespace already present, avoid
            #   psychosis by reusing the existing namespace (even if it means
            #   putting a formerly prefixed node into defaulted namespace form).
            #   Note that this can cause effective non-conformance in some cases
            #   because the XSLT spec says that all namespace nodes must be
            #   copied to the reslt tree (even if this causes psychosis).
            #   There is no mandate that all ns nodes must be manifestd as
            #   matching NS Decls in the serialization, but if the output is
            #   to result tree fragment, the required ns nodes will simply
            #   disappear.
            #
            # - If the prefix exists, but with a different namespace, generate
            #   a new (and probably rather ugly) prefix.
            namespaces = self._namespaces[-1]
            if not prefix or prefix == 'xmlns':
                # Find an existing namespace/prefix pair
                for prefix, inscope_namespace in namespaces.iteritems():
                    if prefix and inscope_namespace == namespace:
                        break
                else:
                    # Generate a new prefix
                    template = self.GENERATED_PREFIX
                    for suffix in itertools.count():
                        prefix = template % suffix
                        if prefix not in namespaces:
                            break
                    namespaces[prefix] = namespace
            elif prefix not in namespaces:
                # Find an existing namespace/prefix pair
                for inscope_prefix, inscope_namespace in namespaces.iteritems():
                    if inscope_prefix and inscope_namespace == namespace:
                        prefix = inscope_prefix
                        break
                else:
                    # Use given namespace/prefix pair
                    namespaces[prefix] = namespace
            elif namespaces[prefix] != namespace:
                # An existing prefix/namespace pair that doesn't match what
                # we're trying to use. First, try to reuse an existing namespace
                # declaration.
                for prefix, inscope_namespace in namespaces.iteritems():
                    if prefix and inscope_namespace == namespace:
                        break
                else:
                    # Generate a new prefix
                    template = self.GENERATED_PREFIX
                    for suffix in itertools.count():
                        prefix = template % suffix
                        if prefix not in namespaces:
                            break
                    namespaces[prefix] = namespace
            # Generate a new node name
            assert prefix, "'prefix' required for non-null namespace"
            name = prefix + ':' + local

        self._attributes[namespace, local] = (name, value)
        return
Esempio n. 15
0
def qname_type(namespace, name):
    prefix, local = splitqname(name)
    return ContentModel(ContentModel.TYPE_NAME, (namespace, local), label=name)