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))
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'})))
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))
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))
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
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')
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)
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)
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), '')
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)
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 |
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
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
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],
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