Ejemplo n.º 1
0
 def test_get_xml_bool_attribute(self):
     elem = etree_element(XSD_ELEMENT,
                          attrib={
                              'a1': 'true',
                              'a2': '1',
                              'a3': 'false',
                              'a4': '0',
                              'a5': 'x'
                          })
     self.assertEqual(get_xml_bool_attribute(elem, 'a1'), True)
     self.assertEqual(get_xml_bool_attribute(elem, 'a2'), True)
     self.assertEqual(get_xml_bool_attribute(elem, 'a3'), False)
     self.assertEqual(get_xml_bool_attribute(elem, 'a4'), False)
     self.assertRaises(TypeError, get_xml_bool_attribute, elem, 'a5')
     self.assertRaises(KeyError, get_xml_bool_attribute, elem, 'a6')
     self.assertEqual(get_xml_bool_attribute(elem, 'a6', True), True)
     self.assertEqual(get_xml_bool_attribute(elem, 'a6', 'true'), True)
     self.assertEqual(get_xml_bool_attribute(elem, 'a6', '1'), True)
     self.assertEqual(get_xml_bool_attribute(elem, 'a6', False), False)
     self.assertEqual(get_xml_bool_attribute(elem, 'a6', 'false'), False)
     self.assertEqual(get_xml_bool_attribute(elem, 'a6', '0'), False)
     self.assertRaises(TypeError, get_xml_bool_attribute, elem, 'a6', 1)
     self.assertRaises(TypeError, get_xml_bool_attribute, elem, 'a6', 0)
     self.assertRaises(TypeError, get_xml_bool_attribute, elem, 'a6',
                       'True')
Ejemplo n.º 2
0
    def _parse(self):
        super(XsdComplexType, self)._parse()
        elem = self.elem
        if elem.tag == XSD_RESTRICTION:
            return  # a local restriction is already parsed by the caller

        if 'abstract' in elem.attrib:
            try:
                self.abstract = get_xml_bool_attribute(elem, 'abstract')
            except ValueError as err:
                self.parse_error(err, elem)

        if 'block' in elem.attrib:
            try:
                self._block = get_xsd_derivation_attribute(
                    elem, 'block', ('extension', 'restriction'))
            except ValueError as err:
                self.parse_error(err, elem)

        if 'final' in elem.attrib:
            try:
                self._final = get_xsd_derivation_attribute(
                    elem, 'final', ('extension', 'restriction'))
            except ValueError as err:
                self.parse_error(err, elem)

        if 'mixed' in elem.attrib:
            try:
                self.mixed = get_xml_bool_attribute(elem, 'mixed')
            except ValueError as err:
                self.parse_error(err, elem)

        try:
            self.name = get_qname(self.target_namespace, elem.attrib['name'])
        except KeyError:
            self.name = None
        else:
            if self.parent is not None:
                self.parse_error(
                    "attribute 'name' not allowed for a local complexType",
                    elem)

        content_elem = self._parse_component(elem,
                                             required=False,
                                             strict=False)
        if content_elem is None or content_elem.tag in \
                {XSD_ATTRIBUTE, XSD_ATTRIBUTE_GROUP, XSD_ANY_ATTRIBUTE}:
            #
            # complexType with empty content
            self.content_type = self.schema.BUILDERS.group_class(
                SEQUENCE_ELEMENT, self.schema, self)
            self._parse_content_tail(elem)

        elif content_elem.tag in {
                XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE
        }:
            #
            # complexType with child elements
            self.content_type = self.schema.BUILDERS.group_class(
                content_elem, self.schema, self)
            self._parse_content_tail(elem)

        elif content_elem.tag == XSD_SIMPLE_CONTENT:
            if 'mixed' in content_elem.attrib:
                self.parse_error(
                    "'mixed' attribute not allowed with simpleContent",
                    content_elem)

            derivation_elem = self._parse_derivation_elem(content_elem)
            if derivation_elem is None:
                return

            self.base_type = self._parse_base_type(derivation_elem)
            if derivation_elem.tag == XSD_RESTRICTION:
                self._parse_simple_content_restriction(derivation_elem,
                                                       self.base_type)
            else:
                self._parse_simple_content_extension(derivation_elem,
                                                     self.base_type)

            if content_elem is not elem[-1]:
                k = 2 if content_elem is not elem[0] else 1
                self.parse_error(
                    "unexpected tag %r after simpleContent declaration:" %
                    elem[k].tag, elem)

        elif content_elem.tag == XSD_COMPLEX_CONTENT:
            #
            # complexType with complexContent restriction/extension
            if 'mixed' in content_elem.attrib:
                self.mixed = content_elem.attrib['mixed'] in ('true', '1')

            derivation_elem = self._parse_derivation_elem(content_elem)
            if derivation_elem is None:
                return

            base_type = self._parse_base_type(derivation_elem,
                                              complex_content=True)
            if derivation_elem.tag == XSD_RESTRICTION:
                self._parse_complex_content_restriction(
                    derivation_elem, base_type)
            else:
                self._parse_complex_content_extension(derivation_elem,
                                                      base_type)

            if content_elem is not elem[-1]:
                k = 2 if content_elem is not elem[0] else 1
                self.parse_error(
                    "unexpected tag %r after complexContent declaration:" %
                    elem[k].tag, elem)
            if self.redefine or base_type is not self:
                self.base_type = base_type

        elif content_elem.tag == XSD_OPEN_CONTENT and self.schema.XSD_VERSION != '1.0':
            self.open_content = None

            if content_elem is elem[-1]:
                self.content_type = self.schema.BUILDERS.group_class(
                    SEQUENCE_ELEMENT, self.schema, self)
            else:
                for child, index in enumerate(elem):
                    if content_elem is not child:
                        continue
                    elif elem[index + 1].tag in {
                            XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE
                    }:
                        self.content_type = self.schema.BUILDERS.group_class(
                            elem[index + 1], self.schema, self)
                    else:
                        self.content_type = self.schema.BUILDERS.group_class(
                            SEQUENCE_ELEMENT, self.schema, self)
                    break
            self._parse_content_tail(elem)

        else:
            if self.schema.validation == 'skip':
                # Also generated by meta-schema validation for 'lax' and 'strict' modes
                self.parse_error(
                    "unexpected tag %r for complexType content:" %
                    content_elem.tag, elem)
            self.content_type = self.schema.create_any_content_group(self)
            self.attributes = self.schema.create_any_attribute_group(self)

        if self.redefine is None:
            if self.base_type is not None and self.base_type.name == self.name:
                self.parse_error("wrong definition with self-reference", elem)
        elif self.base_type is None or self.base_type.name != self.name:
            self.parse_error("wrong redefinition without self-reference", elem)
Ejemplo n.º 3
0
 def default_attributes_apply(self):
     return get_xml_bool_attribute(self.elem,
                                   'defaultAttributesApply',
                                   default=True)
Ejemplo n.º 4
0
    def iter_decode(self, elem, validation='lax', converter=None, **kwargs):
        """
        Creates an iterator for decoding an Element instance.

        :param elem: the Element that has to be decoded.
        :param validation: the validation mode, can be 'lax', 'strict' or 'skip.
        :param converter: an :class:`XMLSchemaConverter` subclass or instance.
        :param kwargs: keyword arguments for the decoding process.
        :return: yields a decoded object, eventually preceded by a sequence of \
        validation or decoding errors.
        """
        if not isinstance(converter, XMLSchemaConverter):
            converter = self.schema.get_converter(converter, **kwargs)
        level = kwargs.pop('level', 0)
        use_defaults = kwargs.get('use_defaults', False)
        value = content = attributes = None

        # Get the instance type: xsi:type or the schema's declaration
        if XSI_TYPE not in elem.attrib:
            xsd_type = self.get_type(elem)
        else:
            xsi_type = elem.attrib[XSI_TYPE]
            try:
                xsd_type = self.maps.lookup_type(converter.unmap_qname(xsi_type))
            except KeyError:
                yield self.validation_error(validation, "unknown type %r" % xsi_type, elem, **kwargs)
                xsd_type = self.get_type(elem)

        # Decode attributes
        attribute_group = getattr(xsd_type, 'attributes', self.attributes)
        for result in attribute_group.iter_decode(elem.attrib, validation, **kwargs):
            if isinstance(result, XMLSchemaValidationError):
                yield self.validation_error(validation, result, elem, **kwargs)
            else:
                attributes = result

        # Checks the xsi:nil attribute of the instance
        if validation != 'skip' and XSI_NIL in elem.attrib:
            if not self.nillable:
                yield self.validation_error(validation, "element is not nillable.", elem, **kwargs)
            try:
                if get_xml_bool_attribute(elem, XSI_NIL):
                    if elem.text is not None:
                        reason = "xsi:nil='true' but the element is not empty."
                        yield self.validation_error(validation, reason, elem, **kwargs)
                    else:
                        element_data = ElementData(elem.tag, None, None, attributes)
                        yield converter.element_decode(element_data, self, level)
                        return
            except TypeError:
                reason = "xsi:nil attribute must has a boolean value."
                yield self.validation_error(validation, reason, elem, **kwargs)

        if xsd_type.is_simple():
            if len(elem) and validation != 'skip':
                reason = "a simpleType element can't has child elements."
                yield self.validation_error(validation, reason, elem, **kwargs)

            text = elem.text
            if self.fixed is not None:
                if text is None:
                    text = self.fixed
                elif text != self.fixed:
                    reason = "must has the fixed value %r." % self.fixed
                    yield self.validation_error(validation, reason, elem, **kwargs)
            elif not text and use_defaults and self.default is not None:
                text = self.default

            if text is None:
                for result in xsd_type.iter_decode('', validation, **kwargs):
                    if isinstance(result, XMLSchemaValidationError):
                        yield self.validation_error(validation, result, elem, **kwargs)
            else:
                for result in xsd_type.iter_decode(text, validation, **kwargs):
                    if isinstance(result, XMLSchemaValidationError):
                        yield self.validation_error(validation, result, elem, **kwargs)
                    else:
                        value = result

        elif xsd_type.has_simple_content():
            if len(elem) and validation != 'skip':
                reason = "a simple content element can't has child elements."
                yield self.validation_error(validation, reason, elem, **kwargs)

            if elem.text is not None:
                text = elem.text or self.default if use_defaults else elem.text
                for result in xsd_type.content_type.iter_decode(text, validation, **kwargs):
                    if isinstance(result, XMLSchemaValidationError):
                        yield self.validation_error(validation, result, elem, **kwargs)
                    else:
                        value = result
        else:
            for result in xsd_type.content_type.iter_decode(elem, validation, converter, level=level + 1, **kwargs):
                if isinstance(result, XMLSchemaValidationError):
                    yield self.validation_error(validation, result, elem, **kwargs)
                else:
                    content = result

        if isinstance(value, Decimal):
            try:
                value = kwargs['decimal_type'](value)
            except (KeyError, TypeError):
                pass
        elif isinstance(value, (AbstractDateTime, Duration)):
            try:
                if kwargs['datetime_types'] is not True:
                    value = elem.text
            except KeyError:
                value = elem.text

        element_data = ElementData(elem.tag, value, content, attributes)
        yield converter.element_decode(element_data, self, level)
        if content is not None:
            del content

        if validation != 'skip':
            for constraint in self.constraints.values():
                for error in constraint(elem):
                    yield self.validation_error(validation, error, elem, **kwargs)
Ejemplo n.º 5
0
 def nillable(self):
     if self._ref is not None:
         return self._ref.nillable
     return get_xml_bool_attribute(self.elem, 'nillable', default=False)
Ejemplo n.º 6
0
    def _parse_attributes(self):
        elem = self.elem
        attrib = elem.attrib
        self._parse_particle(elem)

        try:
            self.qualified = (self.form or self.schema.element_form_default) == 'qualified'
        except ValueError as err:
            self.parse_error(err)

        name = elem.get('name')
        if name is not None:
            if self.parent is None or self.qualified:
                self.name = get_qname(self.target_namespace, attrib['name'])
            else:
                self.name = attrib['name']
        elif self.parent is None:
            self.parse_error("missing 'name' in a global element declaration")
            self.name = elem.get('ref', 'nameless_%s' % str(id(self)))
        elif 'ref' not in attrib:
            self.parse_error("missing both 'name' and 'ref' attributes")
            self.name = elem.get('nameless_%s' % str(id(self)))
        else:
            try:
                element_name = self.schema.resolve_qname(attrib['ref'])
            except ValueError as err:
                self.parse_error(err)
                self.type = self.maps.types[XSD_ANY_TYPE]
                self.name = elem.get('nameless_%s' % str(id(self)))
            else:
                if not element_name:
                    self.parse_error("empty 'ref' attribute")
                    self.type = self.maps.types[XSD_ANY_TYPE]
                    self.name = elem.get('nameless_%s' % str(id(self)))
                else:
                    try:
                        xsd_element = self.maps.lookup_element(element_name)
                    except KeyError:
                        self.parse_error('unknown element %r' % element_name)
                        self.name = element_name
                        self.type = self.maps.types[XSD_ANY_TYPE]
                    else:
                        self._ref = xsd_element
                        self.name = xsd_element.name
                        self.type = xsd_element.type
                        self.qualified = xsd_element.qualified

            for attr_name in ('name', 'type', 'nillable', 'default', 'fixed', 'form',
                              'block', 'abstract', 'final', 'substitutionGroup'):
                if attr_name in attrib:
                    self.parse_error("attribute %r is not allowed when element reference is used." % attr_name)
            return

        if 'default' in attrib and 'fixed' in attrib:
            self.parse_error("'default' and 'fixed' attributes are mutually exclusive.")

        if 'abstract' in elem.attrib:
            try:
                self._abstract = get_xml_bool_attribute(elem, 'abstract')
            except ValueError as err:
                self.parse_error(err, elem)
            else:
                if self.parent is not None:
                    self.parse_error("local scope elements cannot have abstract attribute")

        if 'block' in elem.attrib:
            try:
                self._block = get_xsd_derivation_attribute(
                    elem, 'block', ('extension', 'restriction', 'substitution')
                )
            except ValueError as err:
                self.parse_error(err, elem)

        if self.parent is None:
            self._parse_properties('nillable')

            if 'final' in elem.attrib:
                try:
                    self._final = get_xsd_derivation_attribute(elem, 'final', ('extension', 'restriction'))
                except ValueError as err:
                    self.parse_error(err, elem)

            for attr_name in ('ref', 'form', 'minOccurs', 'maxOccurs'):
                if attr_name in attrib:
                    self.parse_error("attribute %r not allowed in a global element declaration" % attr_name)
        else:
            self._parse_properties('form', 'nillable')

            for attr_name in ('final', 'substitutionGroup'):
                if attr_name in attrib:
                    self.parse_error("attribute %r not allowed in a local element declaration" % attr_name)