def create_node(self, node_element): """Parses the node element to a conformance_validators.Node object. Args: node_element: ElementTree.Element object of a profile node type. Returns: A conformance_validators.Node object of the node element. """ min_occurs = self.get_occurs_number( 'minOccurs', node_element.attrib.get('minOccurs', '1')) max_occurs = self.get_max_occurs(node_element) is_sequence = node_element.tag == constants.XSD_TAG_PREFIX + 'sequence' is_choice = node_element.tag == constants.XSD_TAG_PREFIX + 'choice' node = conformance_validators.Node(min_occurs, max_occurs, is_sequence, is_choice) node_row_type = node_element.attrib.get('type', '') # Strip the DSRF prefix. if (node_row_type and not node_row_type.startswith(constants.DSRF_TYPE_PREFIX)): raise error.XsdParsingFailure( self.dsrf_xsd_file_name, 'The element "%s" with type "%s" does not have the "%s" prefix. This ' 'is likely caused by the type of the parent element not being ' 'recognized as a valid row type. Please ensure that all row types in ' 'in the XSD start with the prefix "%s".' % (node_element.attrib.get('name'), node_row_type, constants.DSRF_TYPE_PREFIX, constants.VALID_ROW_TYPE_PREFIX)) node_row_type = node_row_type.split(':')[-1] if node_row_type: if constants.is_row_type(node_row_type): node.set_row_type( node_row_type[len(constants.VALID_ROW_TYPE_PREFIX):]) return node elif node_row_type in self.complex_elements: # All complex elements are sequences. node.is_sequence = True for element in self.complex_elements[node_row_type]: if element.tag in PROFILE_NODE_TYPES: node.add_child(self.create_node(element)) return node else: raise error.XsdParsingFailure( self.dsrf_xsd_file_name, 'The element "%s" with type "%s" does not exist in the dsrf xsd ' 'file "%s".' % (node_element.attrib.get('name'), node_row_type, self.dsrf_xsd_file_name)) if node_element.getchildren(): for child in node_element: if child.tag in PROFILE_NODE_TYPES: node.add_child(self.create_node(child)) return node
def _parse_elements(self, root, profile_name, parse_complex_types=True, parse_profile=True): """Parses specified children of the root tag.""" profile_node = None profile_names = [] for element in root: try: if parse_profile and self.is_profile(element): profile_names.append(element.attrib['name']) if self.is_profile_or_block(element): if element.attrib['name'].lower( ) == profile_name.lower() + 'block': if parse_profile: profile_node = self.create_profile_node(element) elif parse_complex_types: self.complex_elements[element.attrib['name']] = element except KeyError: raise error.XsdParsingFailure( self.dsrf_xsd_file_name, 'Unexpected complexType without a name: %s' % element.__dict__) return profile_node, profile_names
def get_dsrf_xsd_cells(self, row, logger): """Parses the given row tag to cell validator objects. Args: row: XML tag object of the row to parse. logger: The library logger. Returns: A list of cell validator objects of the row. """ cells = [] for sub_row in row: if sub_row.tag == constants.XSD_TAG_PREFIX + 'sequence': for element in sub_row: if element.tag == constants.XSD_TAG_PREFIX + 'element': cell_name = self.get_cell_name(element) if self.is_complex_type(element): if self.is_pattern(element): cells.append( cell_validators.PatternValidator( self.get_cell_pattern(element), cell_name, logger, self.is_required(element), self.is_repeated(element))) else: # Complex type but not a pattern, raise error. raise error.XsdParsingFailure( self.dsrf_xsd_file_name, 'Unexpected complexType '+ element[1][0][0].tag) else: # Not a complex type, must be simple type. cell_type = self.get_simple_cell_type(element) cells.append( self.get_cell_validator( cell_name, cell_type, self.is_required(element), self.is_repeated(element), logger)) return cells
def get_fixed_string_values(self, root): """Parses the allowed values to a dictionary of {types: [valid values]}. If an IndexError/AttributeError/KeyError is raised in this method, your schema file didn't match the expected structure. For valid schema files, please check the '/schemas' directory. Args: root: An ElementTree.element object of the avs file root. Returns: A dictionary of {types: [valid values]} (eg. {'RecordType':['SY02', 'MW01']}), without union types. """ fixed_string_dict = {} for element in root: if element.tag == constants.XSD_TAG_PREFIX + 'simpleType': element_name = element.attrib['name'] fixed_string_dict[element_name] = [] try: for allowed_value in element[1]: fixed_string_dict[element_name].append( allowed_value.attrib['value']) except (IndexError, KeyError): raise error.XsdParsingFailure( self.avs_xsd_file_name, 'Malformed AVS xsd element: %s.' % element_name) return fixed_string_dict
def get_occurs_number(self, occurs_type, occurs_str): try: return int(occurs_str) except ValueError: raise error.XsdParsingFailure( self.dsrf_xsd_file_name, 'The value "%s" is invalid as a %s. Expected an integer/"unbounded".' % (occurs_str, occurs_type))
def get_avs_location_from_root(self, root): """Inspects the root tag of the profile XSD to find the AVS xsd version.""" for child in root: if child.tag == constants.XSD_TAG_PREFIX + 'import': if child.attrib.get('namespace') == constants.AVS_XSD_NAMESPACE: schema_location = child.attrib['schemaLocation'] unused_directory, avs_version = path.split( path.split(schema_location)[0]) return constants.get_xsd_file('avs', avs_version) raise error.XsdParsingFailure( self.dsrf_xsd_file_name, 'No AVS import found (namespace = %s).' % constants.AVS_XSD_NAMESPACE)
def get_cell_validator(self, cell_name, cell_type, required, repeated, logger): """Creates a cell validator object by the given cell name. Args: cell_name: The cell name (from the schema file). cell_type: The cell type (from the schema file). required: True if the cell is mandatory. repeated: True if the cell is repeated. logger: The library logger. Returns: cell_validator object. """ # Primitive types. if cell_type in VALIDATOR_TYPES_MAP: return VALIDATOR_TYPES_MAP[cell_type](cell_name, logger, required, repeated) # Simple types. if cell_type.startswith(constants.DSRF_TYPE_PREFIX): cell_type = cell_type.split(':')[-1] if cell_type in self.simple_types_map: if (self.simple_types_map[cell_type][1][0].tag == constants.XSD_TAG_PREFIX + 'pattern'): return cell_validators.PatternValidator( self.simple_types_map[cell_type][1][0].attrib['value'], cell_name, logger, required, repeated) # AVS types. cell_type = cell_type.replace(constants.FIXED_STRING_PREFIX, '') if cell_type in self._fixed_string_values: return cell_validators.FixedStringValidator( self._fixed_string_values[cell_type], cell_name, logger, required, repeated) raise error.XsdParsingFailure( path.basename(self.dsrf_xsd_file_name), 'The cell type %s does not ' 'exist in the provided configuration files. Please make sure you use ' 'the right files and version.' % cell_type)