예제 #1
0
    def test_has_xsd_components(self):
        elem = etree_element(XSD_SCHEMA)
        elem.append(etree_element(XSD_ELEMENT))
        self.assertTrue(has_xsd_components(elem))

        elem.clear()
        self.assertFalse(has_xsd_components(elem))
        elem.append(etree_element(XSD_ANNOTATION))
        self.assertFalse(has_xsd_components(elem))
        elem.append(etree_element(XSD_ELEMENT))
        self.assertTrue(has_xsd_components(elem))
        self.assertFalse(has_xsd_components(elem, start=1))
        elem.append(etree_element(XSD_ANNOTATION))
        self.assertRaises(ValueError, list, iter_xsd_components(elem))
예제 #2
0
    def test_complex_type_assertion(self):
        schema = self.check_schema("""
            <complexType name="intRange">
              <attribute name="min" type="int"/>
              <attribute name="max" type="int"/>
              <assert test="@min le @max"/>
            </complexType>""")

        xsd_type = schema.types['intRange']
        xsd_type.decode(etree_element('a', attrib={'min': '10', 'max': '19'}))
        self.assertTrue(xsd_type.is_valid(etree_element('a', attrib={'min': '10', 'max': '19'})))
        self.assertTrue(xsd_type.is_valid(etree_element('a', attrib={'min': '19', 'max': '19'})))
        self.assertFalse(xsd_type.is_valid(etree_element('a', attrib={'min': '25', 'max': '19'})))
        self.assertTrue(xsd_type.is_valid(etree_element('a', attrib={'min': '25', 'max': '100'})))
예제 #3
0
    def test_get_xsd_annotation(self):
        elem = etree_element(XSD_SCHEMA)

        self.assertIsNone(get_xsd_annotation(elem))
        elem.append(etree_element(XSD_ANNOTATION))
        self.assertEqual(get_xsd_annotation(elem), elem[0])
        elem.append(etree_element(XSD_ELEMENT))
        self.assertEqual(get_xsd_annotation(elem), elem[0])

        elem.clear()
        elem.append(etree_element(XSD_ELEMENT))
        self.assertIsNone(get_xsd_annotation(elem))
        elem.append(etree_element(XSD_ANNOTATION))
        self.assertIsNone(get_xsd_annotation(elem))
예제 #4
0
 def test_iter_xsd_components(self):
     elem = etree_element(XSD_SCHEMA)
     self.assertFalse(list(iter_xsd_components(elem)))
     self.assertFalse(list(iter_xsd_components(elem, start=1)))
     elem.append(etree_element(XSD_ANNOTATION))
     self.assertFalse(list(iter_xsd_components(elem)))
     self.assertFalse(list(iter_xsd_components(elem, start=1)))
     elem.append(etree_element(XSD_ELEMENT))
     self.assertEqual(list(iter_xsd_components(elem)), [elem[1]])
     elem.append(etree_element(XSD_SIMPLE_TYPE))
     self.assertEqual(list(iter_xsd_components(elem)), elem[1:])
     self.assertEqual(list(iter_xsd_components(elem, start=1)), [elem[2]])
     elem.append(etree_element(XSD_ANNOTATION))
     self.assertRaises(ValueError, list, iter_xsd_components(elem))
예제 #5
0
    def get_type(self, elem):
        if not self.alternatives:
            return self.type

        if isinstance(elem, ElementData):
            if elem.attributes:
                attrib = {k: raw_xml_encode(v) for k, v in elem.attributes.items()}
                elem = etree_element(elem.tag, attrib=attrib)
            else:
                elem = etree_element(elem.tag)

        for alt in self.alternatives:
            if alt.type is not None and boolean_value(list(alt.token.select(context=XPathContext(root=elem)))):
                return alt.type
        return self.type
예제 #6
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')
예제 #7
0
    def test_get_xsd_component(self):
        elem = etree_element(XSD_SCHEMA)
        self.assertRaises(ValueError, get_xsd_component, elem)
        self.assertIsNone(get_xsd_component(elem, required=False))
        elem.append(etree_element(XSD_ELEMENT))
        self.assertEqual(get_xsd_component(elem), elem[0])
        elem.append(etree_element(XSD_SIMPLE_TYPE))
        self.assertRaises(ValueError, get_xsd_component, elem)
        self.assertEqual(get_xsd_component(elem, strict=False), elem[0])

        elem.clear()
        elem.append(etree_element(XSD_ANNOTATION))
        self.assertRaises(ValueError, get_xsd_component, elem)
        self.assertIsNone(get_xsd_component(elem, required=False))
        elem.append(etree_element(XSD_SIMPLE_TYPE))
        self.assertEqual(get_xsd_component(elem), elem[1])
        elem.append(etree_element(XSD_ELEMENT))
        self.assertRaises(ValueError, get_xsd_component, elem)
        self.assertEqual(get_xsd_component(elem, strict=False), elem[1])

        elem.clear()
        elem.append(etree_element(XSD_ANNOTATION))
        elem.append(etree_element(XSD_ANNOTATION))
        self.assertRaises(ValueError, get_xsd_component, elem, True, False)
예제 #8
0
    def retrieve_schema_source(self, source):
        """
        Returns a schema source that can be used to create an XMLSchema instance.

        :param source: A string or an ElementTree's Element.
        :return: An schema source string, an ElementTree's Element or a full pathname.
        """
        if is_etree_element(source):
            if source.tag in (XSD_SCHEMA, 'schema'):
                return source
            elif get_namespace(source.tag):
                raise XMLSchemaValueError(
                    "source %r namespace has to be empty." % source)
            elif source.tag not in {
                    'element', 'attribute', 'simpleType', 'complexType',
                    'group', 'attributeGroup', 'notation'
            }:
                raise XMLSchemaValueError(
                    "% is not an XSD global definition/declaration." % source)

            root = etree_element('schema',
                                 attrib={
                                     'xmlns:ns': "ns",
                                     'xmlns':
                                     "http://www.w3.org/2001/XMLSchema",
                                     'targetNamespace': "ns",
                                     'elementFormDefault': "qualified",
                                     'version': self.schema_class.XSD_VERSION,
                                 })
            root.append(source)
            return root
        else:
            source = source.strip()
            if not source.startswith('<'):
                return self.casepath(source)
            else:
                return self.SCHEMA_TEMPLATE.format(
                    self.schema_class.XSD_VERSION, source)
예제 #9
0
 def test_get_xsd_derivation_attribute(self):
     elem = etree_element(XSD_ELEMENT,
                          attrib={
                              'a1': 'extension',
                              'a2': ' restriction',
                              'a3': '#all',
                              'a4': 'other',
                              'a5': 'restriction extension restriction ',
                              'a6': 'other restriction'
                          })
     values = ('extension', 'restriction')
     self.assertEqual(get_xsd_derivation_attribute(elem, 'a1', values),
                      'extension')
     self.assertEqual(get_xsd_derivation_attribute(elem, 'a2', values),
                      ' restriction')
     self.assertEqual(get_xsd_derivation_attribute(elem, 'a3', values),
                      'extension restriction')
     self.assertRaises(ValueError, get_xsd_derivation_attribute, elem, 'a4',
                       values)
     self.assertEqual(get_xsd_derivation_attribute(elem, 'a5', values),
                      'restriction extension restriction ')
     self.assertRaises(ValueError, get_xsd_derivation_attribute, elem, 'a6',
                       values)
     self.assertEqual(get_xsd_derivation_attribute(elem, 'a7', values), '')
예제 #10
0
    def _parse_complex_content_extension(self, elem, base_type):
        if 'extension' in base_type.final:
            self.parse_error("the base type is not derivable by extension")

        group_elem = self._parse_component(elem, required=False, strict=False)
        if base_type.is_empty():
            # Empty model extension: don't create a nested group.
            if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
                self.content_type = self.schema.BUILDERS.group_class(
                    group_elem, self.schema, self)
            else:
                # Empty content model
                self.content_type = self.schema.BUILDERS.group_class(
                    elem, self.schema, self)
        else:
            # Set the content type using a dummy sequence element
            sequence_elem = etree_element(XSD_SEQUENCE)
            sequence_elem.text = '\n    '
            content_type = self.schema.BUILDERS.group_class(
                sequence_elem, self.schema, self)

            if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
                # Illegal derivation from a simple content. Applies to both XSD 1.0 and XSD 1.1.
                # For the detailed rule refer to XSD 1.1 documentation:
                #   https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#sec-cos-ct-extends
                if base_type.is_simple() or base_type.has_simple_content():
                    self.parse_error(
                        "base %r is simple or has a simple content." %
                        base_type, elem)
                    base_type = self.maps.types[XSD_ANY_TYPE]

                group = self.schema.BUILDERS.group_class(
                    group_elem, self.schema, self)
                if group.model == 'all':
                    self.parse_error(
                        "Cannot extend a complex content with an all model")

                content_type.append(base_type.content_type)
                content_type.append(group)
                sequence_elem.append(base_type.content_type.elem)
                sequence_elem.append(group.elem)

                # complexContent extension: base type must be a complex type with complex content.
                # A dummy sequence group is added if the base type has not empty content model.
                if base_type.content_type.model == 'all' and base_type.content_type and group \
                        and self.schema.XSD_VERSION == '1.0':
                    self.parse_error(
                        "XSD 1.0 does not allow extension of a not empty 'ALL' model group.",
                        elem)

                if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE:
                    self.parse_error(
                        "base has a different content type (mixed=%r) and the "
                        "extension group is not empty." % base_type.mixed,
                        elem)

            elif not base_type.is_simple(
            ) and not base_type.has_simple_content():
                content_type.append(base_type.content_type)
                sequence_elem.append(base_type.content_type.elem)
                if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE and self.mixed:
                    self.parse_error(
                        "extended type has a mixed content but the base is element-only",
                        elem)

            self.content_type = content_type

        self._parse_content_tail(elem,
                                 derivation='extension',
                                 base_attributes=base_type.attributes)
예제 #11
0
from xmlschema_acue.qnames import XSD_GROUP, XSD_ATTRIBUTE_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE, \
    XSD_ANY_ATTRIBUTE, XSD_ATTRIBUTE, XSD_COMPLEX_CONTENT, XSD_RESTRICTION, XSD_COMPLEX_TYPE, \
    XSD_EXTENSION, XSD_ANY_TYPE, XSD_SIMPLE_CONTENT, XSD_ANY_SIMPLE_TYPE, XSD_OPEN_CONTENT, XSD_ASSERT
from xmlschema_acue.helpers import get_qname, local_name, get_xml_bool_attribute, get_xsd_derivation_attribute
from xmlschema_acue.etree import etree_element

from xmlschema_acue.validators.exceptions import XMLSchemaValidationError, XMLSchemaDecodeError
from xmlschema_acue.validators.xsdbase import XsdType, ValidationMixin
from xmlschema_acue.validators.assertions import XsdAssert
from xmlschema_acue.validators.attributes import XsdAttributeGroup
from xmlschema_acue.validators.simple_types import XsdSimpleType
from xmlschema_acue.validators.groups import XsdGroup

XSD_MODEL_GROUP_TAGS = {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE}

SEQUENCE_ELEMENT = etree_element(XSD_SEQUENCE)


class XsdComplexType(XsdType, ValidationMixin):
    """
    Class for XSD 1.0 'complexType' definitions.
    
    <complexType
      abstract = boolean : false
      block = (#all | List of (extension | restriction))
      final = (#all | List of (extension | restriction))
      id = ID
      mixed = boolean : false
      name = NCName
      {any attributes with non-schema namespace . . .}>
      Content: (annotation?, (simpleContent | complexContent | 
예제 #12
0
    XSD_COMPLEX_TYPE, XSD_SIMPLE_TYPE, XSD_ALTERNATIVE, XSD_ELEMENT, XSD_ANY_TYPE, XSD_UNIQUE, \
    XSD_KEY, XSD_KEYREF, XSI_NIL, XSI_TYPE, XSD_ID
from xmlschema_acue.helpers import get_qname, get_xml_bool_attribute, get_xsd_derivation_attribute, \
    get_xsd_form_attribute, ParticleCounter
from xmlschema_acue.etree import etree_element
from xmlschema_acue.converters import ElementData, raw_xml_encode, XMLSchemaConverter
from xmlschema_acue.xpath import ElementPathMixin

from xmlschema_acue.validators.exceptions import XMLSchemaValidationError
from xmlschema_acue.validators.xsdbase import XsdComponent, XsdType, ValidationMixin, ParticleMixin
from xmlschema_acue.validators.identities import XsdUnique, XsdKey, XsdKeyref
from xmlschema_acue.validators.wildcards import XsdAnyElement


XSD_MODEL_GROUP_TAGS = {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE}
XSD_ATTRIBUTE_GROUP_ELEMENT = etree_element(XSD_ATTRIBUTE_GROUP)


class XsdElement(XsdComponent, ValidationMixin, ParticleMixin, ElementPathMixin):
    """
    Class for XSD 1.0 'element' declarations.
    
    <element
      abstract = boolean : false
      block = (#all | List of (extension | restriction | substitution))
      default = string
      final = (#all | List of (extension | restriction))
      fixed = string
      form = (qualified | unqualified)
      id = ID
      maxOccurs = (nonNegativeInteger | unbounded)  : 1
예제 #13
0
def xsd_builtin_types_factory(meta_schema, xsd_types, atomic_builtin_class=None):
    """
    Builds the dictionary for XML Schema built-in types mapping.
    """
    atomic_builtin_class = atomic_builtin_class or XsdAtomicBuiltin
    if meta_schema.XSD_VERSION == '1.1':
        builtin_types = XSD_11_BUILTIN_TYPES
        facets_map = XSD_11_FACETS_BUILDERS
    else:
        builtin_types = XSD_10_BUILTIN_TYPES
        facets_map = XSD_10_FACETS_BUILDERS

    #
    # Special builtin types.
    #
    # xs:anyType
    # Ref: https://www.w3.org/TR/xmlschema11-1/#builtin-ctd
    any_type = meta_schema.BUILDERS.complex_type_class(
        elem=etree_element(XSD_COMPLEX_TYPE, name=XSD_ANY_TYPE),
        schema=meta_schema,
        parent=None,
        mixed=True
    )
    any_type.content_type = meta_schema.create_any_content_group(any_type)
    any_type.attributes = meta_schema.create_any_attribute_group(any_type)
    xsd_types[XSD_ANY_TYPE] = any_type

    # xs:anySimpleType
    # Ref: https://www.w3.org/TR/xmlschema11-2/#builtin-stds
    xsd_types[XSD_ANY_SIMPLE_TYPE] = XsdSimpleType(
        elem=etree_element(XSD_SIMPLE_TYPE, name=XSD_ANY_SIMPLE_TYPE),
        schema=meta_schema,
        parent=None,
        name=XSD_ANY_SIMPLE_TYPE
    )

    # xs:anyAtomicType
    # Ref: https://www.w3.org/TR/xmlschema11-2/#builtin-stds
    xsd_types[XSD_ANY_ATOMIC_TYPE] = meta_schema.BUILDERS.restriction_class(
        elem=etree_element(XSD_SIMPLE_TYPE, name=XSD_ANY_ATOMIC_TYPE),
        schema=meta_schema,
        parent=None,
        name=XSD_ANY_ATOMIC_TYPE,
        base_type=xsd_types[XSD_ANY_SIMPLE_TYPE]
    )

    for item in builtin_types:
        item = item.copy()
        name = item['name']
        try:
            elem, schema = xsd_types[name]
        except KeyError:
            # If builtin type element is missing create a dummy element. Necessary for the
            # meta-schema XMLSchema.xsd of XSD 1.1, that not includes builtins declarations.
            elem = etree_element(XSD_SIMPLE_TYPE, name=name, id=name)
        else:
            if schema is not meta_schema:
                raise XMLSchemaValueError("loaded entry schema doesn't match meta_schema!")

        if 'base_type' in item:
            base_type = item['base_type'] = xsd_types[item['base_type']]
        else:
            base_type = None

        facets = item.pop('facets', None)
        builtin_type = atomic_builtin_class(elem, meta_schema, **item)
        if isinstance(facets, (list, tuple)):
            built_facets = builtin_type.facets
            for e in facets:
                if is_etree_element(e):
                    cls = facets_map[e.tag]
                    built_facets[e.tag] = cls(e, meta_schema, builtin_type, base_type)
                elif callable(e):
                    if None in facets:
                        raise XMLSchemaValueError("Almost one callable for facet group!!")
                    built_facets[None] = e
                else:
                    raise XMLSchemaValueError("Wrong type for item %r" % e)
            builtin_type.facets = built_facets

        xsd_types[name] = builtin_type
예제 #14
0
def boolean_to_python(s):
    if s in ('true', '1'):
        return True
    elif s in ('false', '0'):
        return False
    else:
        raise XMLSchemaValueError('not a boolean value: %r' % s)


def python_to_boolean(obj):
    return unicode_type(obj).lower()


#
# Element facets instances for builtin types.
PRESERVE_WHITE_SPACE_ELEMENT = etree_element(XSD_WHITE_SPACE, value='preserve')
COLLAPSE_WHITE_SPACE_ELEMENT = etree_element(XSD_WHITE_SPACE, value='collapse')
REPLACE_WHITE_SPACE_ELEMENT = etree_element(XSD_WHITE_SPACE, value='replace')


XSD_COMMON_BUILTIN_TYPES = (
    # ***********************
    # *** Primitive types ***
    # ***********************

    # --- String Types ---
    {
        'name': XSD_STRING,
        'python_type': (unicode_type, str),
        'admitted_facets': STRING_FACETS,
        'facets': [PRESERVE_WHITE_SPACE_ELEMENT],
예제 #15
0
from xmlschema_acue.etree import etree_element
from xmlschema_acue.qnames import XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE, XSD_COMPLEX_TYPE, \
    XSD_ELEMENT, XSD_ANY, XSD_RESTRICTION, XSD_EXTENSION
from xmlschema_acue.helpers import get_qname, local_name
from xmlschema_acue.converters import XMLSchemaConverter

from xmlschema_acue.validators.exceptions import XMLSchemaValidationError, XMLSchemaChildrenValidationError
from xmlschema_acue.validators.xsdbase import ValidationMixin, XsdComponent, XsdType
from xmlschema_acue.validators.elements import XsdElement
from xmlschema_acue.validators.wildcards import XsdAnyElement
from xmlschema_acue.validators.models import MAX_MODEL_DEPTH, ParticleMixin, ModelGroup, ModelVisitor

ANY_ELEMENT = etree_element(XSD_ANY,
                            attrib={
                                'namespace': '##any',
                                'processContents': 'lax',
                                'minOccurs': '0',
                                'maxOccurs': 'unbounded'
                            })


class XsdGroup(XsdComponent, ModelGroup, ValidationMixin):
    """
    A class for XSD 1.0 model group definitions.

    <group
      id = ID
      maxOccurs = (nonNegativeInteger | unbounded)  : 1
      minOccurs = nonNegativeInteger : 1
      name = NCName
      ref = QName