#!/usr/bin/env python

#
# Generated Mon May  2 14:23:33 2011 by parse_xsd.py version 0.4.
#
# A summary of available specifications can be found at:
# https://wiki.oasis-open.org/security/FrontPage
#
# saml core specifications to be found at:
# if any question arise please query the following pdf.
# http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
# The specification was later updated with errata, and the new version is here:
# https://www.oasis-open.org/committees/download.php/56776/sstc-saml-core-errata-2.0-wd-07.pdf
#


import base64

from saml2.validate import valid_ipv4, MustValueError
from saml2.validate import valid_ipv6
from saml2.validate import ShouldValueError
from saml2.validate import valid_domain_name

import saml2
from saml2 import SamlBase

import six
from saml2 import xmldsig as ds
from saml2 import xmlenc as xenc

# authentication information fields
NAMESPACE = 'urn:oasis:names:tc:SAML:2.0:assertion'

# xmlschema definition
XSD = "xs"
# xmlschema templates and extensions
XS_NAMESPACE = 'http://www.w3.org/2001/XMLSchema'
# xmlschema-instance, which contains several builtin attributes
XSI_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance'
# xml soap namespace
NS_SOAP_ENC = "http://schemas.xmlsoap.org/soap/encoding/"
# type definitions for xmlschemas
XSI_TYPE = '{%s}type' % XSI_NAMESPACE
# nil type definition for xmlschemas 
XSI_NIL = '{%s}nil' % XSI_NAMESPACE

# idp and sp communicate usually about a subject(NameID)
# the format determines the category the subject is in

# custom subject
NAMEID_FORMAT_UNSPECIFIED = (
    "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified")
# subject as email address
NAMEID_FORMAT_EMAILADDRESS = (
    "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")
# subject as x509 key
NAMEID_FORMAT_X509SUBJECTNAME = (
    "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName")
# subject as windows domain name
NAMEID_FORMAT_WINDOWSDOMAINQUALIFIEDNAME = (
    "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName")
# subject from a kerberos instance
NAMEID_FORMAT_KERBEROS = (
    "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos")
# subject as name
NAMEID_FORMAT_ENTITY = (
    "urn:oasis:names:tc:SAML:2.0:nameid-format:entity")
# linked subject
NAMEID_FORMAT_PERSISTENT = (
    "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent")
# annonymous subject
NAMEID_FORMAT_TRANSIENT = (
    "urn:oasis:names:tc:SAML:2.0:nameid-format:transient")
# subject avaiable in encrypted format
NAMEID_FORMAT_ENCRYPTED = (
    "urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted")
# dicc for avaiable formats
NAMEID_FORMATS_SAML2 = (
    ('NAMEID_FORMAT_EMAILADDRESS', NAMEID_FORMAT_EMAILADDRESS),
    ('NAMEID_FORMAT_ENCRYPTED', NAMEID_FORMAT_ENCRYPTED),
    ('NAMEID_FORMAT_ENTITY', NAMEID_FORMAT_ENTITY),
    ('NAMEID_FORMAT_PERSISTENT', NAMEID_FORMAT_PERSISTENT),
    ('NAMEID_FORMAT_TRANSIENT', NAMEID_FORMAT_TRANSIENT),
    ('NAMEID_FORMAT_UNSPECIFIED', NAMEID_FORMAT_UNSPECIFIED),
)

# a profile outlines a set of rules describing how to embed SAML assertions.
# https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
# The specification was later updated with errata, and the new version is here:
# https://www.oasis-open.org/committees/download.php/56782/sstc-saml-profiles-errata-2.0-wd-07.pdf

# XML based values for SAML attributes  
PROFILE_ATTRIBUTE_BASIC = (
    "urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic")

# an AuthnRequest is made to initiate authentication
# authenticate the request with login credentials
AUTHN_PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
# authenticate the request with login credentials, over tls/https
AUTHN_PASSWORD_PROTECTED = \
    "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"

# attribute statements is key:value metadata shared with your app

# custom format
NAME_FORMAT_UNSPECIFIED = (
    "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified")
# uri format
NAME_FORMAT_URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
# XML-based format
NAME_FORMAT_BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
# dicc for avaiable formats
NAME_FORMATS_SAML2 = (
    ('NAME_FORMAT_BASIC', NAME_FORMAT_BASIC),
    ('NAME_FORMAT_URI', NAME_FORMAT_URI),
    ('NAME_FORMAT_UNSPECIFIED', NAME_FORMAT_UNSPECIFIED),
)

# the SAML authority's decision can be predetermined by arbitrary context

# the specified action is permitted
DECISION_TYPE_PERMIT = "Permit"
# the specified action is denied
DECISION_TYPE_DENY = "Deny"
# the SAML authority cannot determine if the action is permitted or denied
DECISION_TYPE_INDETERMINATE = "Indeterminate"


# consent attributes determine wether consent has been given and under
# what conditions

# no claim to consent is made
CONSENT_UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
# consent has been obtained
CONSENT_OBTAINED = "urn:oasis:names:tc:SAML:2.0:consent:obtained"
# consent has been obtained before the message has been initiated
CONSENT_PRIOR = "urn:oasis:names:tc:SAML:2.0:consent:prior"
# consent has been obtained implicitly
CONSENT_IMPLICIT = "urn:oasis:names:tc:SAML:2.0:consent:current-implicit"
# consent has been obtained explicitly
CONSENT_EXPLICIT = "urn:oasis:names:tc:SAML:2.0:consent:current-explicit"
# no consent has been obtained
CONSENT_UNAVAILABLE = "urn:oasis:names:tc:SAML:2.0:consent:unavailable"
# no consent is needed.
CONSENT_INAPPLICABLE = "urn:oasis:names:tc:SAML:2.0:consent:inapplicable"


# Subject confirmation methods(scm), can be issued, besides the subject itself
# by third parties.
# http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0.pdf

# the 3rd party is identified on behalf of the subject given private/public key
SCM_HOLDER_OF_KEY = "urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"
# the 3rd party is identified by subject confirmation and must include a security header
# signing its content.
SCM_SENDER_VOUCHES = "urn:oasis:names:tc:SAML:2.0:cm:sender-vouches"
# a bearer token is issued instead.
SCM_BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer"


class AttributeValueBase(SamlBase):
    def __init__(self,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        self._extatt = {}

        SamlBase.__init__(self,
                          text=None,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        if self._extatt:
            self.extension_attributes = self._extatt

        if text:
            self.set_text(text)
        elif not extension_elements:
            self.extension_attributes = {XSI_NIL: 'true'}
        elif XSI_TYPE in self.extension_attributes:
            del self.extension_attributes[XSI_TYPE]

    def __setattr__(self, key, value):
        if key == "text":
            self.set_text(value)
        else:
            SamlBase.__setattr__(self, key, value)

    def verify(self):
        if not self.text and not self.extension_elements:
            if not self.extension_attributes:
                raise Exception(
                    "Attribute value base should not have extension attributes"
                )
            if self.extension_attributes[XSI_NIL] != "true":
                raise Exception(
                    "Attribute value base should not have extension attributes"
                )
            return True
        else:
            SamlBase.verify(self)

    def set_type(self, typ):
        try:
            del self.extension_attributes[XSI_NIL]
        except (AttributeError, KeyError):
            pass

        try:
            self.extension_attributes[XSI_TYPE] = typ
        except AttributeError:
            self._extatt[XSI_TYPE] = typ

        if typ.startswith('xs:'):
            try:
                self.extension_attributes['xmlns:xs'] = XS_NAMESPACE
            except AttributeError:
                self._extatt['xmlns:xs'] = XS_NAMESPACE

        if typ.startswith('xsd:'):
            try:
                self.extension_attributes['xmlns:xsd'] = XS_NAMESPACE
            except AttributeError:
                self._extatt['xmlns:xsd'] = XS_NAMESPACE

    def get_type(self):
        try:
            return self.extension_attributes[XSI_TYPE]
        except (KeyError, AttributeError):
            try:
                return self._extatt[XSI_TYPE]
            except KeyError:
                return ""

    def clear_type(self):
        try:
            del self.extension_attributes[XSI_TYPE]
        except KeyError:
            pass
        try:
            del self._extatt[XSI_TYPE]
        except KeyError:
            pass

    def set_text(self, value, base64encode=False):
        def _wrong_type_value(xsd, value):
            msg = 'Type and value do not match: {xsd}:{type}:{value}'
            msg = msg.format(xsd=xsd, type=type(value), value=value)
            raise ValueError(msg)

        # only work with six.string_types
        if isinstance(value, six.binary_type):
            value = value.decode('utf-8')

        type_to_xsd = {
            str:        'string',
            int:        'integer',
            float:      'float',
            bool:       'boolean',
            type(None): '',
        }

        # entries of xsd-types each declaring:
        # - a corresponding python type
        # - a function to turn a string into that type
        # - a function to turn that type into a text-value
        xsd_types_props = {
            'string': {
                'type': str,
                'to_type': str,
                'to_text': str,
            },
            'integer': {
                'type': int,
                'to_type': int,
                'to_text': str,
            },
            'short': {
                'type': int,
                'to_type': int,
                'to_text': str,
            },
            'int': {
                'type': int,
                'to_type': int,
                'to_text': str,
            },
            'long': {
                'type': int,
                'to_type': int,
                'to_text': str,
            },
            'float': {
                'type': float,
                'to_type': float,
                'to_text': str,
            },
            'double': {
                'type': float,
                'to_type': float,
                'to_text': str,
            },
            'boolean': {
                'type': bool,
                'to_type': lambda x: {
                    'true': True,
                    'false': False,
                }[str(x).lower()],
                'to_text': lambda x: str(x).lower(),
            },
            'base64Binary': {
                'type': str,
                'to_type': str,
                'to_text': (
                    lambda x: base64.encodebytes(x.encode()) if base64encode else x
                ),
            },
            'anyType': {
                'type': type(value),
                'to_type': lambda x: x,
                'to_text': lambda x: x,
            },
            '': {
                'type': type(None),
                'to_type': lambda x: None,
                'to_text': lambda x: '',
            },
        }

        xsd_string = (
            'base64Binary' if base64encode
            else self.get_type()
            or type_to_xsd.get(type(value)))

        xsd_ns, xsd_type = (
            ['', type(None)] if xsd_string is None
            else ['', ''] if xsd_string == ''
            else [
                XSD if xsd_string in xsd_types_props else '',
                xsd_string
            ] if ':' not in xsd_string
            else xsd_string.split(':', 1))

        xsd_type_props = xsd_types_props.get(xsd_type, {})
        valid_type = xsd_type_props.get('type', type(None))
        to_type = xsd_type_props.get('to_type', str)
        to_text = xsd_type_props.get('to_text', str)

        # cast to correct type before type-checking
        if type(value) is str and valid_type is not str:
            try:
                value = to_type(value)
            except (TypeError, ValueError, KeyError) as e:
                # the cast failed
                _wrong_type_value(xsd=xsd_type, value=value)

        if type(value) is not valid_type:
            _wrong_type_value(xsd=xsd_type, value=value)

        text = to_text(value)
        self.set_type(
            '{ns}:{type}'.format(ns=xsd_ns, type=xsd_type) if xsd_ns
            else xsd_type if xsd_type
            else '')
        SamlBase.__setattr__(self, 'text', text)
        return self

    def harvest_element_tree(self, tree):
        # Fill in the instance members from the contents of the XML tree.
        for child in tree:
            self._convert_element_tree_to_member(child)
        for attribute, value in iter(tree.attrib.items()):
            self._convert_element_attribute_to_member(attribute, value)

        # if we have added children to this node
        # we consider whitespace insignificant
        # and remove/trim/strip whitespace
        # and expect to not have actual text content
        text = (
            tree.text.strip()
            if tree.text and self.extension_elements
            else tree.text
        )
        if text:
            #print("set_text:", tree.text)
            # clear type
            #self.clear_type()
            self.set_text(text)

        # if we have added a text node
        # or other children to this node
        # remove the nil marker
        if text or self.extension_elements:
            if XSI_NIL in self.extension_attributes:
                del self.extension_attributes[XSI_NIL]


class BaseIDAbstractType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:BaseIDAbstractType element """

    c_tag = 'BaseIDAbstractType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_attributes['NameQualifier'] = ('name_qualifier', 'string', False)
    c_attributes['SPNameQualifier'] = ('sp_name_qualifier', 'string', False)

    def __init__(self,
                 name_qualifier=None,
                 sp_name_qualifier=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.name_qualifier = name_qualifier
        self.sp_name_qualifier = sp_name_qualifier


class NameIDType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:NameIDType element """

    c_tag = 'NameIDType'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'string'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_attributes['NameQualifier'] = ('name_qualifier', 'string', False)
    c_attributes['SPNameQualifier'] = ('sp_name_qualifier', 'string', False)
    c_attributes['Format'] = ('format', 'anyURI', False)
    c_attributes['SPProvidedID'] = ('sp_provided_id', 'string', False)

    def __init__(self,
                 name_qualifier=None,
                 sp_name_qualifier=None,
                 format=None,
                 sp_provided_id=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.name_qualifier = name_qualifier
        self.sp_name_qualifier = sp_name_qualifier
        self.format = format
        self.sp_provided_id = sp_provided_id


def name_id_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(NameIDType_, xml_string)


class EncryptedElementType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:EncryptedElementType element
    """

    c_tag = 'EncryptedElementType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{http://www.w3.org/2001/04/xmlenc#}EncryptedData'] = (
        'encrypted_data',
        xenc.EncryptedData)
    c_children['{http://www.w3.org/2001/04/xmlenc#}EncryptedKey'] = (
        'encrypted_key',
        [xenc.EncryptedKey])
    c_cardinality['encrypted_key'] = {"min": 0}
    c_child_order.extend(['encrypted_data', 'encrypted_key'])

    def __init__(self,
                 encrypted_data=None,
                 encrypted_key=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.encrypted_data = encrypted_data
        self.encrypted_key = encrypted_key or []


def encrypted_element_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(EncryptedElementType_, xml_string)


class EncryptedID(EncryptedElementType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:EncryptedID element """

    c_tag = 'EncryptedID'
    c_namespace = NAMESPACE
    c_children = EncryptedElementType_.c_children.copy()
    c_attributes = EncryptedElementType_.c_attributes.copy()
    c_child_order = EncryptedElementType_.c_child_order[:]
    c_cardinality = EncryptedElementType_.c_cardinality.copy()


def encrypted_id_from_string(xml_string):
    return saml2.create_class_from_xml_string(EncryptedID, xml_string)


class Issuer(NameIDType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Issuer element """

    c_tag = 'Issuer'
    c_namespace = NAMESPACE
    c_children = NameIDType_.c_children.copy()
    c_attributes = NameIDType_.c_attributes.copy()
    c_child_order = NameIDType_.c_child_order[:]
    c_cardinality = NameIDType_.c_cardinality.copy()


def issuer_from_string(xml_string):
    return saml2.create_class_from_xml_string(Issuer, xml_string)


class AssertionIDRef(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AssertionIDRef element """

    c_tag = 'AssertionIDRef'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'NCName'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def assertion_id_ref_from_string(xml_string):
    return saml2.create_class_from_xml_string(AssertionIDRef, xml_string)


class AssertionURIRef(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AssertionURIRef element """

    c_tag = 'AssertionURIRef'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'anyURI'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def assertion_uri_ref_from_string(xml_string):
    return saml2.create_class_from_xml_string(AssertionURIRef, xml_string)


class SubjectConfirmationDataType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:SubjectConfirmationDataType
    element """

    c_tag = 'SubjectConfirmationDataType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_attributes['NotBefore'] = ('not_before', 'dateTime', False)
    c_attributes['NotOnOrAfter'] = ('not_on_or_after', 'dateTime', False)
    c_attributes['Recipient'] = ('recipient', 'anyURI', False)
    c_attributes['InResponseTo'] = ('in_response_to', 'NCName', False)
    c_attributes['Address'] = ('address', 'string', False)
    c_any = {"namespace": "##any", "processContents": "lax", "minOccurs": "0",
             "maxOccurs": "unbounded"}
    c_any_attribute = {"namespace": "##other", "processContents": "lax"}

    def __init__(self,
                 not_before=None,
                 not_on_or_after=None,
                 recipient=None,
                 in_response_to=None,
                 address=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.not_before = not_before
        self.not_on_or_after = not_on_or_after
        self.recipient = recipient
        self.in_response_to = in_response_to
        self.address = address


def subject_confirmation_data_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(SubjectConfirmationDataType_,
                                              xml_string)


class KeyInfoConfirmationDataType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:KeyInfoConfirmationDataType
    element """

    c_tag = 'KeyInfoConfirmationDataType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{http://www.w3.org/2000/09/xmldsig#}KeyInfo'] = ('key_info',
                                                                 [ds.KeyInfo])
    c_cardinality['key_info'] = {"min": 1}
    c_child_order.extend(['key_info'])

    def __init__(self,
                 key_info=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.key_info = key_info or []


def key_info_confirmation_data_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(KeyInfoConfirmationDataType_,
                                              xml_string)


class ConditionAbstractType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:ConditionAbstractType
    element """

    c_tag = 'ConditionAbstractType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


class Audience(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Audience element """

    c_tag = 'Audience'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'anyURI'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def audience_from_string(xml_string):
    return saml2.create_class_from_xml_string(Audience, xml_string)


class OneTimeUseType_(ConditionAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:OneTimeUseType element """

    c_tag = 'OneTimeUseType'
    c_namespace = NAMESPACE
    c_children = ConditionAbstractType_.c_children.copy()
    c_attributes = ConditionAbstractType_.c_attributes.copy()
    c_child_order = ConditionAbstractType_.c_child_order[:]
    c_cardinality = ConditionAbstractType_.c_cardinality.copy()


def one_time_use_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(OneTimeUseType_, xml_string)


class ProxyRestrictionType_(ConditionAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:ProxyRestrictionType element
    """

    c_tag = 'ProxyRestrictionType'
    c_namespace = NAMESPACE
    c_children = ConditionAbstractType_.c_children.copy()
    c_attributes = ConditionAbstractType_.c_attributes.copy()
    c_child_order = ConditionAbstractType_.c_child_order[:]
    c_cardinality = ConditionAbstractType_.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Audience'] = ('audience',
                                                                     [Audience])
    c_cardinality['audience'] = {"min": 0}
    c_attributes['Count'] = ('count', 'nonNegativeInteger', False)
    c_child_order.extend(['audience'])

    def __init__(self,
                 audience=None,
                 count=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        ConditionAbstractType_.__init__(
            self, text=text, extension_elements=extension_elements,
            extension_attributes=extension_attributes)
        self.audience = audience or []
        self.count = count


def proxy_restriction_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(ProxyRestrictionType_, xml_string)


class EncryptedAssertion(EncryptedElementType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:EncryptedAssertion element """

    c_tag = 'EncryptedAssertion'
    c_namespace = NAMESPACE
    c_children = EncryptedElementType_.c_children.copy()
    c_attributes = EncryptedElementType_.c_attributes.copy()
    c_child_order = EncryptedElementType_.c_child_order[:]
    c_cardinality = EncryptedElementType_.c_cardinality.copy()


def encrypted_assertion_from_string(xml_string):
    return saml2.create_class_from_xml_string(EncryptedAssertion, xml_string)


class StatementAbstractType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:StatementAbstractType element
    """

    c_tag = 'StatementAbstractType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


class SubjectLocalityType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:SubjectLocalityType element """

    c_tag = 'SubjectLocalityType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_attributes['Address'] = ('address', 'string', False)
    c_attributes['DNSName'] = ('dns_name', 'string', False)

    def __init__(self,
                 address=None,
                 dns_name=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.address = address
        self.dns_name = dns_name


def subject_locality_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(SubjectLocalityType_, xml_string)


class AuthnContextClassRef(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthnContextClassRef element
    """

    c_tag = 'AuthnContextClassRef'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'anyURI'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def authn_context_class_ref_from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthnContextClassRef, xml_string)


class AuthnContextDeclRef(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthnContextDeclRef element """

    c_tag = 'AuthnContextDeclRef'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'anyURI'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def authn_context_decl_ref_from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthnContextDeclRef, xml_string)


class AuthnContextDecl(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthnContextDecl element """

    c_tag = 'AuthnContextDecl'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'anyType'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def authn_context_decl_from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthnContextDecl, xml_string)


class AuthenticatingAuthority(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthenticatingAuthority
    element """

    c_tag = 'AuthenticatingAuthority'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'anyURI'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def authenticating_authority_from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthenticatingAuthority,
                                              xml_string)


class DecisionType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:DecisionType element """

    c_tag = 'DecisionType'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'string', 'enumeration': ['Permit', 'Deny',
                                                      'Indeterminate']}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def decision_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(DecisionType_, xml_string)


class ActionType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:ActionType element """

    c_tag = 'ActionType'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'string'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_attributes['Namespace'] = ('namespace', 'anyURI', True)

    def __init__(self,
                 namespace=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.namespace = namespace


def action_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(ActionType_, xml_string)


class AttributeValue(AttributeValueBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AttributeValue element """

    c_tag = 'AttributeValue'
    c_namespace = NAMESPACE
    c_value_type = {'base': 'anyType'}
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()


def attribute_value_from_string(xml_string):
    return saml2.create_class_from_xml_string(AttributeValue, xml_string)


class EncryptedAttribute(EncryptedElementType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:EncryptedAttribute element """

    c_tag = 'EncryptedAttribute'
    c_namespace = NAMESPACE
    c_children = EncryptedElementType_.c_children.copy()
    c_attributes = EncryptedElementType_.c_attributes.copy()
    c_child_order = EncryptedElementType_.c_child_order[:]
    c_cardinality = EncryptedElementType_.c_cardinality.copy()


def encrypted_attribute_from_string(xml_string):
    return saml2.create_class_from_xml_string(EncryptedAttribute, xml_string)


class BaseID(BaseIDAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:BaseID element """

    c_tag = 'BaseID'
    c_namespace = NAMESPACE
    c_children = BaseIDAbstractType_.c_children.copy()
    c_attributes = BaseIDAbstractType_.c_attributes.copy()
    c_child_order = BaseIDAbstractType_.c_child_order[:]
    c_cardinality = BaseIDAbstractType_.c_cardinality.copy()


def base_id_from_string(xml_string):
    return saml2.create_class_from_xml_string(BaseID, xml_string)


class NameID(NameIDType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:NameID element

    From the Oasis SAML2 Technical Overview:

    "The <NameID> element within a <Subject> offers the ability to provide name
     identifiers in a number of different formats. SAML's predefined formats
     include: Email address, X.509 subject name, Windows domain qualified name,
     Kerberos principal name, Entity identifier, Persistent identifier,
     Transient identifier."
     """

    c_tag = 'NameID'
    c_namespace = NAMESPACE
    c_children = NameIDType_.c_children.copy()
    c_attributes = NameIDType_.c_attributes.copy()
    c_child_order = NameIDType_.c_child_order[:]
    c_cardinality = NameIDType_.c_cardinality.copy()


def name_id_from_string(xml_string):
    return saml2.create_class_from_xml_string(NameID, xml_string)


class SubjectConfirmationData(SubjectConfirmationDataType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:SubjectConfirmationData
    element """

    c_tag = 'SubjectConfirmationData'
    c_namespace = NAMESPACE
    c_children = SubjectConfirmationDataType_.c_children.copy()
    c_attributes = SubjectConfirmationDataType_.c_attributes.copy()
    c_child_order = SubjectConfirmationDataType_.c_child_order[:]
    c_cardinality = SubjectConfirmationDataType_.c_cardinality.copy()


def subject_confirmation_data_from_string(xml_string):
    return saml2.create_class_from_xml_string(SubjectConfirmationData,
                                              xml_string)


class Condition(ConditionAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Condition element """

    c_tag = 'Condition'
    c_namespace = NAMESPACE
    c_children = ConditionAbstractType_.c_children.copy()
    c_attributes = ConditionAbstractType_.c_attributes.copy()
    c_child_order = ConditionAbstractType_.c_child_order[:]
    c_cardinality = ConditionAbstractType_.c_cardinality.copy()


def condition_from_string(xml_string):
    return saml2.create_class_from_xml_string(Condition, xml_string)


class AudienceRestrictionType_(ConditionAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AudienceRestrictionType
    element """

    c_tag = 'AudienceRestrictionType'
    c_namespace = NAMESPACE
    c_children = ConditionAbstractType_.c_children.copy()
    c_attributes = ConditionAbstractType_.c_attributes.copy()
    c_child_order = ConditionAbstractType_.c_child_order[:]
    c_cardinality = ConditionAbstractType_.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Audience'] = ('audience',
                                                                     [Audience])
    c_cardinality['audience'] = {"min": 1}
    c_child_order.extend(['audience'])

    def __init__(self,
                 audience=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        ConditionAbstractType_.__init__(
            self, text=text, extension_elements=extension_elements,
            extension_attributes=extension_attributes)
        self.audience = audience or []


def audience_restriction_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(AudienceRestrictionType_,
                                              xml_string)


class OneTimeUse(OneTimeUseType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:OneTimeUse element """

    c_tag = 'OneTimeUse'
    c_namespace = NAMESPACE
    c_children = OneTimeUseType_.c_children.copy()
    c_attributes = OneTimeUseType_.c_attributes.copy()
    c_child_order = OneTimeUseType_.c_child_order[:]
    c_cardinality = OneTimeUseType_.c_cardinality.copy()


def one_time_use_from_string(xml_string):
    return saml2.create_class_from_xml_string(OneTimeUse, xml_string)


class ProxyRestriction(ProxyRestrictionType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:ProxyRestriction element """

    c_tag = 'ProxyRestriction'
    c_namespace = NAMESPACE
    c_children = ProxyRestrictionType_.c_children.copy()
    c_attributes = ProxyRestrictionType_.c_attributes.copy()
    c_child_order = ProxyRestrictionType_.c_child_order[:]
    c_cardinality = ProxyRestrictionType_.c_cardinality.copy()


def proxy_restriction_from_string(xml_string):
    return saml2.create_class_from_xml_string(ProxyRestriction, xml_string)


class Statement(StatementAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Statement element """

    c_tag = 'Statement'
    c_namespace = NAMESPACE
    c_children = StatementAbstractType_.c_children.copy()
    c_attributes = StatementAbstractType_.c_attributes.copy()
    c_child_order = StatementAbstractType_.c_child_order[:]
    c_cardinality = StatementAbstractType_.c_cardinality.copy()


def statement_from_string(xml_string):
    return saml2.create_class_from_xml_string(Statement, xml_string)


class SubjectLocality(SubjectLocalityType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:SubjectLocality element """

    c_tag = 'SubjectLocality'
    c_namespace = NAMESPACE
    c_children = SubjectLocalityType_.c_children.copy()
    c_attributes = SubjectLocalityType_.c_attributes.copy()
    c_child_order = SubjectLocalityType_.c_child_order[:]
    c_cardinality = SubjectLocalityType_.c_cardinality.copy()

    def verify(self):
        if self.address:
            # dotted-decimal IPv4 or RFC3513 IPv6 address
            if valid_ipv4(self.address) or valid_ipv6(self.address):
                pass
            else:
                raise ShouldValueError("Not an IPv4 or IPv6 address")
        elif self.dns_name:
            valid_domain_name(self.dns_name)

        return SubjectLocalityType_.verify(self)


def subject_locality_from_string(xml_string):
    return saml2.create_class_from_xml_string(SubjectLocality, xml_string)


class AuthnContextType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthnContextType element """

    c_tag = 'AuthnContextType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children[
        '{urn:oasis:names:tc:SAML:2.0:assertion}AuthnContextClassRef'] = (
            'authn_context_class_ref', AuthnContextClassRef)
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AuthnContextDecl'] = (
        'authn_context_decl',
        AuthnContextDecl)
    c_cardinality['authn_context_decl'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AuthnContextDeclRef'] = (
        'authn_context_decl_ref',
        AuthnContextDeclRef)
    c_cardinality['authn_context_decl_ref'] = {"min": 0, "max": 1}
    c_children[
        '{urn:oasis:names:tc:SAML:2.0:assertion}AuthenticatingAuthority'] = (
            'authenticating_authority', [AuthenticatingAuthority])
    c_cardinality['authenticating_authority'] = {"min": 0}
    c_child_order.extend(['authn_context_class_ref', 'authn_context_decl',
                          'authn_context_decl_ref', 'authenticating_authority'])

    def __init__(self,
                 authn_context_class_ref=None,
                 authn_context_decl=None,
                 authn_context_decl_ref=None,
                 authenticating_authority=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.authn_context_class_ref = authn_context_class_ref
        self.authn_context_decl = authn_context_decl
        self.authn_context_decl_ref = authn_context_decl_ref
        self.authenticating_authority = authenticating_authority or []

    def verify(self):
        if self.authn_context_decl and self.authn_context_decl_ref:
            raise Exception(
                "Invalid Response: "
                "Cannot have both <AuthnContextDecl> and <AuthnContextDeclRef>"
            )
        return SamlBase.verify(self)


def authn_context_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthnContextType_, xml_string)


class Action(ActionType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Action element """

    c_tag = 'Action'
    c_namespace = NAMESPACE
    c_children = ActionType_.c_children.copy()
    c_attributes = ActionType_.c_attributes.copy()
    c_child_order = ActionType_.c_child_order[:]
    c_cardinality = ActionType_.c_cardinality.copy()


def action_from_string(xml_string):
    return saml2.create_class_from_xml_string(Action, xml_string)


class AttributeType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AttributeType element """

    c_tag = 'AttributeType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue'] = (
        'attribute_value',
        [AttributeValue])
    c_cardinality['attribute_value'] = {"min": 0}
    c_attributes['Name'] = ('name', 'string', True)
    c_attributes['NameFormat'] = ('name_format', 'anyURI', False)
    c_attributes['FriendlyName'] = ('friendly_name', 'string', False)
    c_child_order.extend(['attribute_value'])
    c_any_attribute = {"namespace": "##other", "processContents": "lax"}

    def __init__(self,
                 attribute_value=None,
                 name=None,
                 name_format=NAME_FORMAT_URI,
                 friendly_name=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.attribute_value = attribute_value or []
        self.name = name
        self.name_format = name_format
        self.friendly_name = friendly_name

    # when consuming such elements, default to NAME_FORMAT_UNSPECIFIED as NameFormat
    def harvest_element_tree(self, tree):
        tree.attrib.setdefault('NameFormat', NAME_FORMAT_UNSPECIFIED)
        SamlBase.harvest_element_tree(self, tree)


def attribute_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(AttributeType_, xml_string)


class SubjectConfirmationType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:SubjectConfirmationType
    element """

    c_tag = 'SubjectConfirmationType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}BaseID'] = ('base_id',
                                                                   BaseID)
    c_cardinality['base_id'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}NameID'] = ('name_id',
                                                                   NameID)
    c_cardinality['name_id'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedID'] = (
        'encrypted_id',
        EncryptedID)
    c_cardinality['encrypted_id'] = {"min": 0, "max": 1}
    c_children[
        '{urn:oasis:names:tc:SAML:2.0:assertion}SubjectConfirmationData'] = (
            'subject_confirmation_data', SubjectConfirmationData)
    c_cardinality['subject_confirmation_data'] = {"min": 0, "max": 1}
    c_attributes['Method'] = ('method', 'anyURI', True)
    c_child_order.extend(['base_id', 'name_id', 'encrypted_id',
                          'subject_confirmation_data'])

    def __init__(self,
                 base_id=None,
                 name_id=None,
                 encrypted_id=None,
                 subject_confirmation_data=None,
                 method=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.base_id = base_id
        self.name_id = name_id
        self.encrypted_id = encrypted_id
        self.subject_confirmation_data = subject_confirmation_data
        self.method = method


def subject_confirmation_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(SubjectConfirmationType_,
                                              xml_string)


class AudienceRestriction(AudienceRestrictionType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AudienceRestriction element """

    c_tag = 'AudienceRestriction'
    c_namespace = NAMESPACE
    c_children = AudienceRestrictionType_.c_children.copy()
    c_attributes = AudienceRestrictionType_.c_attributes.copy()
    c_child_order = AudienceRestrictionType_.c_child_order[:]
    c_cardinality = AudienceRestrictionType_.c_cardinality.copy()


def audience_restriction_from_string(xml_string):
    return saml2.create_class_from_xml_string(AudienceRestriction, xml_string)


class AuthnContext(AuthnContextType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthnContext element """

    c_tag = 'AuthnContext'
    c_namespace = NAMESPACE
    c_children = AuthnContextType_.c_children.copy()
    c_attributes = AuthnContextType_.c_attributes.copy()
    c_child_order = AuthnContextType_.c_child_order[:]
    c_cardinality = AuthnContextType_.c_cardinality.copy()


def authn_context_from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthnContext, xml_string)


class Attribute(AttributeType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Attribute element """

    c_tag = 'Attribute'
    c_namespace = NAMESPACE
    c_children = AttributeType_.c_children.copy()
    c_attributes = AttributeType_.c_attributes.copy()
    c_child_order = AttributeType_.c_child_order[:]
    c_cardinality = AttributeType_.c_cardinality.copy()


def attribute_from_string(xml_string):
    return saml2.create_class_from_xml_string(Attribute, xml_string)


class SubjectConfirmation(SubjectConfirmationType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:SubjectConfirmation element """

    c_tag = 'SubjectConfirmation'
    c_namespace = NAMESPACE
    c_children = SubjectConfirmationType_.c_children.copy()
    c_attributes = SubjectConfirmationType_.c_attributes.copy()
    c_child_order = SubjectConfirmationType_.c_child_order[:]
    c_cardinality = SubjectConfirmationType_.c_cardinality.copy()


def subject_confirmation_from_string(xml_string):
    return saml2.create_class_from_xml_string(SubjectConfirmation, xml_string)


class ConditionsType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:ConditionsType element """

    c_tag = 'ConditionsType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Condition'] = (
        'condition',
        [Condition])
    c_cardinality['condition'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AudienceRestriction'] = (
        'audience_restriction',
        [AudienceRestriction])
    c_cardinality['audience_restriction'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}OneTimeUse'] = (
        'one_time_use',
        [OneTimeUse])
    c_cardinality['one_time_use'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}ProxyRestriction'] = (
        'proxy_restriction',
        [ProxyRestriction])
    c_cardinality['proxy_restriction'] = {"min": 0}
    c_attributes['NotBefore'] = ('not_before', 'dateTime', False)
    c_attributes['NotOnOrAfter'] = ('not_on_or_after', 'dateTime', False)
    c_child_order.extend(['condition', 'audience_restriction', 'one_time_use',
                          'proxy_restriction'])

    def __init__(self,
                 condition=None,
                 audience_restriction=None,
                 one_time_use=None,
                 proxy_restriction=None,
                 not_before=None,
                 not_on_or_after=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.condition = condition or []
        self.audience_restriction = audience_restriction or []
        self.one_time_use = one_time_use or []
        self.proxy_restriction = proxy_restriction or []
        self.not_before = not_before
        self.not_on_or_after = not_on_or_after

    def verify(self):
        if self.one_time_use:
            if len(self.one_time_use) != 1:
                raise Exception("Cannot be used more than once")
        if self.proxy_restriction:
            if len(self.proxy_restriction) != 1:
                raise Exception("Cannot be used more than once")

        return SamlBase.verify(self)


def conditions_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(ConditionsType_, xml_string)


class AuthnStatementType_(StatementAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthnStatementType element """

    c_tag = 'AuthnStatementType'
    c_namespace = NAMESPACE
    c_children = StatementAbstractType_.c_children.copy()
    c_attributes = StatementAbstractType_.c_attributes.copy()
    c_child_order = StatementAbstractType_.c_child_order[:]
    c_cardinality = StatementAbstractType_.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}SubjectLocality'] = (
        'subject_locality', SubjectLocality)
    c_cardinality['subject_locality'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AuthnContext'] = (
        'authn_context', AuthnContext)
    c_attributes['AuthnInstant'] = ('authn_instant', 'dateTime', True)
    c_attributes['SessionIndex'] = ('session_index', 'string', False)
    c_attributes['SessionNotOnOrAfter'] = ('session_not_on_or_after',
                                           'dateTime', False)
    c_child_order.extend(['subject_locality', 'authn_context'])

    def __init__(self,
                 subject_locality=None,
                 authn_context=None,
                 authn_instant=None,
                 session_index=None,
                 session_not_on_or_after=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        StatementAbstractType_.__init__(
            self, text=text, extension_elements=extension_elements,
            extension_attributes=extension_attributes)
        self.subject_locality = subject_locality
        self.authn_context = authn_context
        self.authn_instant = authn_instant
        self.session_index = session_index
        self.session_not_on_or_after = session_not_on_or_after


def authn_statement_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthnStatementType_, xml_string)


class AttributeStatementType_(StatementAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AttributeStatementType
    element """

    c_tag = 'AttributeStatementType'
    c_namespace = NAMESPACE
    c_children = StatementAbstractType_.c_children.copy()
    c_attributes = StatementAbstractType_.c_attributes.copy()
    c_child_order = StatementAbstractType_.c_child_order[:]
    c_cardinality = StatementAbstractType_.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Attribute'] = (
        'attribute',
        [Attribute])
    c_cardinality['attribute'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedAttribute'] = (
        'encrypted_attribute',
        [EncryptedAttribute])
    c_cardinality['encrypted_attribute'] = {"min": 0}
    c_child_order.extend(['attribute', 'encrypted_attribute'])

    def __init__(self,
                 attribute=None,
                 encrypted_attribute=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        StatementAbstractType_.__init__(
            self, text=text, extension_elements=extension_elements,
            extension_attributes=extension_attributes)
        self.attribute = attribute or []
        self.encrypted_attribute = encrypted_attribute or []


def attribute_statement_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(AttributeStatementType_,
                                              xml_string)


class SubjectType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:SubjectType element """

    c_tag = 'SubjectType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}BaseID'] = ('base_id',
                                                                   BaseID)
    c_cardinality['base_id'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}NameID'] = ('name_id',
                                                                   NameID)
    c_cardinality['name_id'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedID'] = (
        'encrypted_id', EncryptedID)
    c_cardinality['encrypted_id'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}SubjectConfirmation'] = (
        'subject_confirmation', [SubjectConfirmation])
    c_cardinality['subject_confirmation'] = {"min": 0}
    c_child_order.extend(['base_id', 'name_id', 'encrypted_id',
                          'subject_confirmation'])

    def __init__(self,
                 base_id=None,
                 name_id=None,
                 encrypted_id=None,
                 subject_confirmation=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.base_id = base_id
        self.name_id = name_id
        self.encrypted_id = encrypted_id
        self.subject_confirmation = subject_confirmation or []


def subject_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(SubjectType_, xml_string)


class Conditions(ConditionsType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Conditions element """

    c_tag = 'Conditions'
    c_namespace = NAMESPACE
    c_children = ConditionsType_.c_children.copy()
    c_attributes = ConditionsType_.c_attributes.copy()
    c_child_order = ConditionsType_.c_child_order[:]
    c_cardinality = ConditionsType_.c_cardinality.copy()


def conditions_from_string(xml_string):
    return saml2.create_class_from_xml_string(Conditions, xml_string)


class AuthnStatement(AuthnStatementType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthnStatement element """

    c_tag = 'AuthnStatement'
    c_namespace = NAMESPACE
    c_children = AuthnStatementType_.c_children.copy()
    c_attributes = AuthnStatementType_.c_attributes.copy()
    c_child_order = AuthnStatementType_.c_child_order[:]
    c_cardinality = AuthnStatementType_.c_cardinality.copy()


def authn_statement_from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthnStatement, xml_string)


class AttributeStatement(AttributeStatementType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AttributeStatement element """

    c_tag = 'AttributeStatement'
    c_namespace = NAMESPACE
    c_children = AttributeStatementType_.c_children.copy()
    c_attributes = AttributeStatementType_.c_attributes.copy()
    c_child_order = AttributeStatementType_.c_child_order[:]
    c_cardinality = AttributeStatementType_.c_cardinality.copy()


def attribute_statement_from_string(xml_string):
    return saml2.create_class_from_xml_string(AttributeStatement, xml_string)


class Subject(SubjectType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Subject element """

    c_tag = 'Subject'
    c_namespace = NAMESPACE
    c_children = SubjectType_.c_children.copy()
    c_attributes = SubjectType_.c_attributes.copy()
    c_child_order = SubjectType_.c_child_order[:]
    c_cardinality = SubjectType_.c_cardinality.copy()


def subject_from_string(xml_string):
    return saml2.create_class_from_xml_string(Subject, xml_string)


#..................
# ['AuthzDecisionStatement', 'EvidenceType', 'AdviceType', 'Evidence',
# 'Assertion', 'AssertionType', 'AuthzDecisionStatementType', 'Advice']
class EvidenceType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:EvidenceType element """

    c_tag = 'EvidenceType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AssertionIDRef'] = (
        'assertion_id_ref', [AssertionIDRef])
    c_cardinality['assertion_id_ref'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AssertionURIRef'] = (
        'assertion_uri_ref', [AssertionURIRef])
    c_cardinality['assertion_uri_ref'] = {"min": 0}
    c_cardinality['assertion'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedAssertion'] = (
        'encrypted_assertion', [EncryptedAssertion])
    c_cardinality['encrypted_assertion'] = {"min": 0}
    c_child_order.extend(['assertion_id_ref', 'assertion_uri_ref', 'assertion',
                          'encrypted_assertion'])

    def __init__(self,
                 assertion_id_ref=None,
                 assertion_uri_ref=None,
                 assertion=None,
                 encrypted_assertion=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.assertion_id_ref = assertion_id_ref or []
        self.assertion_uri_ref = assertion_uri_ref or []
        self.assertion = assertion or []
        self.encrypted_assertion = encrypted_assertion or []


def evidence_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(EvidenceType_, xml_string)


class Evidence(EvidenceType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Evidence element """

    c_tag = 'Evidence'
    c_namespace = NAMESPACE
    c_children = EvidenceType_.c_children.copy()
    c_attributes = EvidenceType_.c_attributes.copy()
    c_child_order = EvidenceType_.c_child_order[:]
    c_cardinality = EvidenceType_.c_cardinality.copy()


def evidence_from_string(xml_string):
    return saml2.create_class_from_xml_string(Evidence, xml_string)


class AuthzDecisionStatementType_(StatementAbstractType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthzDecisionStatementType
    element """

    c_tag = 'AuthzDecisionStatementType'
    c_namespace = NAMESPACE
    c_children = StatementAbstractType_.c_children.copy()
    c_attributes = StatementAbstractType_.c_attributes.copy()
    c_child_order = StatementAbstractType_.c_child_order[:]
    c_cardinality = StatementAbstractType_.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Action'] = (
        'action', [Action])
    c_cardinality['action'] = {"min": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Evidence'] = (
        'evidence', Evidence)
    c_cardinality['evidence'] = {"min": 0, "max": 1}
    c_attributes['Resource'] = ('resource', 'anyURI', True)
    c_attributes['Decision'] = ('decision', DecisionType_, True)
    c_child_order.extend(['action', 'evidence'])

    def __init__(self,
                 action=None,
                 evidence=None,
                 resource=None,
                 decision=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        StatementAbstractType_.__init__(
            self, text=text, extension_elements=extension_elements,
            extension_attributes=extension_attributes)
        self.action = action or []
        self.evidence = evidence
        self.resource = resource
        self.decision = decision


def authz_decision_statement_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthzDecisionStatementType_,
                                              xml_string)


class AuthzDecisionStatement(AuthzDecisionStatementType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AuthzDecisionStatement
    element """

    c_tag = 'AuthzDecisionStatement'
    c_namespace = NAMESPACE
    c_children = AuthzDecisionStatementType_.c_children.copy()
    c_attributes = AuthzDecisionStatementType_.c_attributes.copy()
    c_child_order = AuthzDecisionStatementType_.c_child_order[:]
    c_cardinality = AuthzDecisionStatementType_.c_cardinality.copy()


def authz_decision_statement_from_string(xml_string):
    return saml2.create_class_from_xml_string(AuthzDecisionStatement,
                                              xml_string)


#..................
# ['Assertion', 'AssertionType', 'AdviceType', 'Advice']
class AssertionType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AssertionType element """

    c_tag = 'AssertionType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Issuer'] = ('issuer',
                                                                   Issuer)
    c_children['{http://www.w3.org/2000/09/xmldsig#}Signature'] = ('signature',
                                                                   ds.Signature)
    c_cardinality['signature'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Subject'] = ('subject',
                                                                    Subject)
    c_cardinality['subject'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Conditions'] = (
        'conditions', Conditions)
    c_cardinality['conditions'] = {"min": 0, "max": 1}
    c_cardinality['advice'] = {"min": 0, "max": 1}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Statement'] = (
        'statement', [Statement])
    c_cardinality['statement'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AuthnStatement'] = (
        'authn_statement', [AuthnStatement])
    c_cardinality['authn_statement'] = {"min": 0}
    c_children[
        '{urn:oasis:names:tc:SAML:2.0:assertion}AuthzDecisionStatement'] = (
            'authz_decision_statement', [AuthzDecisionStatement])
    c_cardinality['authz_decision_statement'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AttributeStatement'] = (
        'attribute_statement', [AttributeStatement])
    c_cardinality['attribute_statement'] = {"min": 0}
    c_attributes['Version'] = ('version', 'string', True)
    c_attributes['ID'] = ('id', 'ID', True)
    c_attributes['IssueInstant'] = ('issue_instant', 'dateTime', True)
    c_child_order.extend(['issuer', 'signature', 'subject', 'conditions',
                          'advice', 'statement', 'authn_statement',
                          'authz_decision_statement', 'attribute_statement'])

    def __init__(self,
                 issuer=None,
                 signature=None,
                 subject=None,
                 conditions=None,
                 advice=None,
                 statement=None,
                 authn_statement=None,
                 authz_decision_statement=None,
                 attribute_statement=None,
                 version=None,
                 id=None,
                 issue_instant=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.issuer = issuer
        self.signature = signature
        self.subject = subject
        self.conditions = conditions
        self.advice = advice
        self.statement = statement or []
        self.authn_statement = authn_statement or []
        self.authz_decision_statement = authz_decision_statement or []
        self.attribute_statement = attribute_statement or []
        self.version = version
        self.id = id
        self.issue_instant = issue_instant

    def verify(self):
        # If no statement MUST contain a subject element
        if self.attribute_statement or self.statement or \
                self.authn_statement or self.authz_decision_statement:
            pass
        elif not self.subject:
            raise MustValueError(
                "If no statement MUST contain a subject element")

        if self.authn_statement and not self.subject:
            raise MustValueError(
                "An assertion with an AuthnStatement must contain a Subject")

        return SamlBase.verify(self)


def assertion_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(AssertionType_, xml_string)


class Assertion(AssertionType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Assertion element """

    c_tag = 'Assertion'
    c_namespace = NAMESPACE
    c_children = AssertionType_.c_children.copy()
    c_attributes = AssertionType_.c_attributes.copy()
    c_child_order = AssertionType_.c_child_order[:]
    c_cardinality = AssertionType_.c_cardinality.copy()


def assertion_from_string(xml_string):
    return saml2.create_class_from_xml_string(Assertion, xml_string)


class AdviceType_(SamlBase):
    """The urn:oasis:names:tc:SAML:2.0:assertion:AdviceType element """

    c_tag = 'AdviceType'
    c_namespace = NAMESPACE
    c_children = SamlBase.c_children.copy()
    c_attributes = SamlBase.c_attributes.copy()
    c_child_order = SamlBase.c_child_order[:]
    c_cardinality = SamlBase.c_cardinality.copy()
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AssertionIDRef'] = (
        'assertion_id_ref', [AssertionIDRef])
    c_cardinality['assertion_id_ref'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}AssertionURIRef'] = (
        'assertion_uri_ref', [AssertionURIRef])
    c_cardinality['assertion_uri_ref'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Assertion'] = (
        'assertion', [Assertion])
    c_cardinality['assertion'] = {"min": 0}
    c_children['{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedAssertion'] = (
        'encrypted_assertion', [EncryptedAssertion])
    c_cardinality['encrypted_assertion'] = {"min": 0}
    c_child_order.extend(['assertion_id_ref', 'assertion_uri_ref', 'assertion',
                          'encrypted_assertion'])
    c_any = {"namespace": "##other", "processContents": "lax"}

    def __init__(self,
                 assertion_id_ref=None,
                 assertion_uri_ref=None,
                 assertion=None,
                 encrypted_assertion=None,
                 text=None,
                 extension_elements=None,
                 extension_attributes=None):
        SamlBase.__init__(self,
                          text=text,
                          extension_elements=extension_elements,
                          extension_attributes=extension_attributes)
        self.assertion_id_ref = assertion_id_ref or []
        self.assertion_uri_ref = assertion_uri_ref or []
        self.assertion = assertion or []
        self.encrypted_assertion = encrypted_assertion or []


def advice_type__from_string(xml_string):
    return saml2.create_class_from_xml_string(AdviceType_, xml_string)


class Advice(AdviceType_):
    """The urn:oasis:names:tc:SAML:2.0:assertion:Advice element """

    c_tag = 'Advice'
    c_namespace = NAMESPACE
    c_children = AdviceType_.c_children.copy()
    c_attributes = AdviceType_.c_attributes.copy()
    c_child_order = AdviceType_.c_child_order[:]
    c_cardinality = AdviceType_.c_cardinality.copy()


def advice_from_string(xml_string):
    return saml2.create_class_from_xml_string(Advice, xml_string)


# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
EvidenceType_.c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Assertion'] = (
    'assertion', [Assertion])
Evidence.c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Assertion'] = (
    'assertion', [Assertion])
AssertionType_.c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Advice'] = (
    'advice', Advice)
Assertion.c_children['{urn:oasis:names:tc:SAML:2.0:assertion}Advice'] = (
    'advice', Advice)
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AG_IDNameQualifiers = [
    ('NameQualifier', 'string', False),
    ('SPNameQualifier', 'string', False),
]

ELEMENT_FROM_STRING = {
    BaseID.c_tag: base_id_from_string,
    NameID.c_tag: name_id_from_string,
    NameIDType_.c_tag: name_id_type__from_string,
    EncryptedElementType_.c_tag: encrypted_element_type__from_string,
    EncryptedID.c_tag: encrypted_id_from_string,
    Issuer.c_tag: issuer_from_string,
    AssertionIDRef.c_tag: assertion_id_ref_from_string,
    AssertionURIRef.c_tag: assertion_uri_ref_from_string,
    Assertion.c_tag: assertion_from_string,
    AssertionType_.c_tag: assertion_type__from_string,
    Subject.c_tag: subject_from_string,
    SubjectType_.c_tag: subject_type__from_string,
    SubjectConfirmation.c_tag: subject_confirmation_from_string,
    SubjectConfirmationType_.c_tag: subject_confirmation_type__from_string,
    SubjectConfirmationData.c_tag: subject_confirmation_data_from_string,
    SubjectConfirmationDataType_.c_tag:
    subject_confirmation_data_type__from_string,
    KeyInfoConfirmationDataType_.c_tag:
    key_info_confirmation_data_type__from_string,
    Conditions.c_tag: conditions_from_string,
    ConditionsType_.c_tag: conditions_type__from_string,
    Condition.c_tag: condition_from_string,
    AudienceRestriction.c_tag: audience_restriction_from_string,
    AudienceRestrictionType_.c_tag: audience_restriction_type__from_string,
    Audience.c_tag: audience_from_string,
    OneTimeUse.c_tag: one_time_use_from_string,
    OneTimeUseType_.c_tag: one_time_use_type__from_string,
    ProxyRestriction.c_tag: proxy_restriction_from_string,
    ProxyRestrictionType_.c_tag: proxy_restriction_type__from_string,
    Advice.c_tag: advice_from_string,
    AdviceType_.c_tag: advice_type__from_string,
    EncryptedAssertion.c_tag: encrypted_assertion_from_string,
    Statement.c_tag: statement_from_string,
    AuthnStatement.c_tag: authn_statement_from_string,
    AuthnStatementType_.c_tag: authn_statement_type__from_string,
    SubjectLocality.c_tag: subject_locality_from_string,
    SubjectLocalityType_.c_tag: subject_locality_type__from_string,
    AuthnContext.c_tag: authn_context_from_string,
    AuthnContextType_.c_tag: authn_context_type__from_string,
    AuthnContextClassRef.c_tag: authn_context_class_ref_from_string,
    AuthnContextDeclRef.c_tag: authn_context_decl_ref_from_string,
    AuthnContextDecl.c_tag: authn_context_decl_from_string,
    AuthenticatingAuthority.c_tag: authenticating_authority_from_string,
    AuthzDecisionStatement.c_tag: authz_decision_statement_from_string,
    AuthzDecisionStatementType_.c_tag:
    authz_decision_statement_type__from_string,
    DecisionType_.c_tag: decision_type__from_string,
    Action.c_tag: action_from_string,
    ActionType_.c_tag: action_type__from_string,
    Evidence.c_tag: evidence_from_string,
    EvidenceType_.c_tag: evidence_type__from_string,
    AttributeStatement.c_tag: attribute_statement_from_string,
    AttributeStatementType_.c_tag: attribute_statement_type__from_string,
    Attribute.c_tag: attribute_from_string,
    AttributeType_.c_tag: attribute_type__from_string,
    AttributeValue.c_tag: attribute_value_from_string,
    EncryptedAttribute.c_tag: encrypted_attribute_from_string,
}

ELEMENT_BY_TAG = {
    'BaseID': BaseID,
    'NameID': NameID,
    'NameIDType': NameIDType_,
    'EncryptedElementType': EncryptedElementType_,
    'EncryptedID': EncryptedID,
    'Issuer': Issuer,
    'AssertionIDRef': AssertionIDRef,
    'AssertionURIRef': AssertionURIRef,
    'Assertion': Assertion,
    'AssertionType': AssertionType_,
    'Subject': Subject,
    'SubjectType': SubjectType_,
    'SubjectConfirmation': SubjectConfirmation,
    'SubjectConfirmationType': SubjectConfirmationType_,
    'SubjectConfirmationData': SubjectConfirmationData,
    'SubjectConfirmationDataType': SubjectConfirmationDataType_,
    'KeyInfoConfirmationDataType': KeyInfoConfirmationDataType_,
    'Conditions': Conditions,
    'ConditionsType': ConditionsType_,
    'Condition': Condition,
    'AudienceRestriction': AudienceRestriction,
    'AudienceRestrictionType': AudienceRestrictionType_,
    'Audience': Audience,
    'OneTimeUse': OneTimeUse,
    'OneTimeUseType': OneTimeUseType_,
    'ProxyRestriction': ProxyRestriction,
    'ProxyRestrictionType': ProxyRestrictionType_,
    'Advice': Advice,
    'AdviceType': AdviceType_,
    'EncryptedAssertion': EncryptedAssertion,
    'Statement': Statement,
    'AuthnStatement': AuthnStatement,
    'AuthnStatementType': AuthnStatementType_,
    'SubjectLocality': SubjectLocality,
    'SubjectLocalityType': SubjectLocalityType_,
    'AuthnContext': AuthnContext,
    'AuthnContextType': AuthnContextType_,
    'AuthnContextClassRef': AuthnContextClassRef,
    'AuthnContextDeclRef': AuthnContextDeclRef,
    'AuthnContextDecl': AuthnContextDecl,
    'AuthenticatingAuthority': AuthenticatingAuthority,
    'AuthzDecisionStatement': AuthzDecisionStatement,
    'AuthzDecisionStatementType': AuthzDecisionStatementType_,
    'DecisionType': DecisionType_,
    'Action': Action,
    'ActionType': ActionType_,
    'Evidence': Evidence,
    'EvidenceType': EvidenceType_,
    'AttributeStatement': AttributeStatement,
    'AttributeStatementType': AttributeStatementType_,
    'Attribute': Attribute,
    'AttributeType': AttributeType_,
    'AttributeValue': AttributeValue,
    'EncryptedAttribute': EncryptedAttribute,
    'BaseIDAbstractType': BaseIDAbstractType_,
    'ConditionAbstractType': ConditionAbstractType_,
    'StatementAbstractType': StatementAbstractType_,
}


def factory(tag, **kwargs):
    return ELEMENT_BY_TAG[tag](**kwargs)
