def find_des(): for i in range(nitf_details.des_subheader_offsets.size): subhead_bytes = nitf_details.get_des_subheader_bytes(i) if nitf_details.nitf_version == '02.00': des_header = DataExtensionHeader0.from_bytes(subhead_bytes, start=0) elif nitf_details.nitf_version == '02.10': des_header = DataExtensionHeader.from_bytes(subhead_bytes, start=0) else: raise ValueError('Got unhandled NITF version {}'.format( nitf_details.nitf_version)) if subhead_bytes.startswith(b'DEXML_DATA_CONTENT'): des_bytes = nitf_details.get_des_bytes(i).decode( 'utf-8').strip().encode() # noinspection PyBroadException try: root_node, xml_ns = parse_xml_from_string(des_bytes) if 'SIDD' in root_node.tag: # namespace makes this ugly sidd_des.append( (i, des_bytes, root_node, xml_ns, des_header)) elif 'SICD' in root_node.tag: sicd_des.append( (i, des_bytes, root_node, xml_ns, des_header)) except Exception: continue elif subhead_bytes.startswith(b'DESIDD_XML'): # This is an old format SIDD des_bytes = nitf_details.get_des_bytes(i).decode( 'utf-8').strip().encode() try: root_node, xml_ns = parse_xml_from_string(des_bytes) if 'SIDD' in root_node.tag: # namespace makes this ugly sidd_des.append( (i, des_bytes, root_node, xml_ns, des_header)) except Exception as e: logger.exception( 'SIDD: Old-style SIDD DES header at index {}, but failed parsing' .format(i)) continue elif subhead_bytes.startswith(b'DESICD_XML'): # This is an old format SICD des_bytes = nitf_details.get_des_bytes(i).decode( 'utf-8').strip().encode() try: root_node, xml_ns = parse_xml_from_string(des_bytes) if 'SICD' in root_node.tag: # namespace makes this ugly sicd_des.append( (i, des_bytes, root_node, xml_ns, des_header)) except Exception as e: logger.exception( 'SIDD: Old-style SICD DES header at index {}, but failed parsing' .format(i)) continue
def _find_sidd(self): self._is_sidd = False if self.des_subheader_offsets is None: return self._sidd_meta = [] self._sicd_meta = [] for i in range(self.des_subheader_offsets.size): subhead_bytes = self.get_des_subheader_bytes(i) if subhead_bytes.startswith(b'DEXML_DATA_CONTENT'): des_bytes = self.get_des_bytes(i) try: root_node, xml_ns = parse_xml_from_string(des_bytes) if 'SIDD' in root_node.tag: self._is_sidd = True self._sidd_meta.append(SIDDType.from_node(root_node, xml_ns, ns_key='default')) elif 'SICD' in root_node.tag: self._sicd_meta.append(SICDType.from_node(root_node, xml_ns, ns_key='default')) except Exception as e: logger.error('Failed checking des xml header at index {} with error {}'.format(i, e)) continue elif subhead_bytes.startswith(b'DESIDD_XML'): # This is an old format SIDD header des_bytes = self.get_des_bytes(i) try: root_node, xml_ns = parse_xml_from_string(des_bytes) if 'SIDD' in root_node.tag: self._is_sidd = True self._sidd_meta.append(SIDDType.from_node(root_node, xml_ns, ns_key='default')) except Exception as e: logger.error( 'We found an apparent old-style SIDD DES header at index {},\n\t' 'but failed parsing with error {}'.format(i, e)) continue elif subhead_bytes.startswith(b'DESICD_XML'): # This is an old format SICD header des_bytes = self.get_des_bytes(i) try: root_node, xml_ns = parse_xml_from_string(des_bytes) if 'SICD' in root_node.tag: self._sicd_meta.append(SICDType.from_node(root_node, xml_ns, ns_key='default')) except Exception as e: logger.error( 'We found an apparent old-style SICD DES header at index {},\n\t' 'but failed parsing with error {}'.format(i, e)) continue if not self._is_sidd: return for sicd in self._sicd_meta: sicd.derive()
def check_data_extension_headers(): # type: () -> (str, Union[DataExtensionHeader, DataExtensionHeader0]) sicd_des = [] for i in range(nitf_details.des_subheader_offsets.size): subhead_bytes = nitf_details.get_des_subheader_bytes(i) des_bytes = None if subhead_bytes.startswith(b'DEXML_DATA_CONTENT'): des_bytes = nitf_details.get_des_bytes(i) elif subhead_bytes.startswith(b'DESIDD_XML'): raise ValueError( 'This file contains an old format SIDD DES, and should be a SIDD file' ) elif subhead_bytes.startswith(b'DESICD_XML'): des_bytes = nitf_details.get_des_bytes(i) if des_bytes is None: continue # compare the SICD structure and the des header structure if nitf_details.nitf_version == '02.00': des_header = DataExtensionHeader0.from_bytes(subhead_bytes, start=0) elif nitf_details.nitf_version == '02.10': des_header = DataExtensionHeader.from_bytes(subhead_bytes, start=0) else: raise ValueError('Got unhandled NITF version {}'.format( nitf_details.nitf_version)) try: des_bytes = des_bytes.decode('utf-8').strip().encode() root_node, xml_ns = parse_xml_from_string(des_bytes) # namespace makes this ugly if 'SIDD' in root_node.tag: raise ValueError( 'This file contains a SIDD DES, and should be a SIDD file' ) elif 'SICD' in root_node.tag: sicd_des.append((i, des_bytes, des_header)) except Exception as e: logger.error( 'Failed parsing the xml DES entry {} as xml'.format(i)) raise e if len(sicd_des) == 0: raise ValueError( 'No SICD DES values found, so this is not a viable SICD file') elif len(sicd_des) > 1: raise ValueError('Multiple SICD DES values found at indices {},\n' 'so this is not a viable SICD file'.format( [entry[0] for entry in sicd_des])) return sicd_des[0][1], sicd_des[0][2]
def from_xml_string(cls, xml_string): """ Construct the research object from an xml string. Parameters ---------- xml_string : str|bytes Returns ------- ResearchType """ root_node, xml_ns = parse_xml_from_string(xml_string) ns_key = 'default' if 'default' in xml_ns else None return cls.from_node(root_node, xml_ns=xml_ns, ns_key=ns_key)
def _evaluate_xml_string_validity(xml_string=None): """ Check the validity of the SIDD xml, as defined by the given string. Parameters ---------- xml_string : str|bytes Returns ------- is_valid : bool sidd_urn : str sidd : SIDDType1|SIDDType2 """ root_node, xml_ns = parse_xml_from_string(xml_string) if 'default' not in xml_ns: raise ValueError( 'Could not properly interpret the namespace collection from xml\n{}'.format(xml_ns)) # todo: validate the xml namespace elements here sidd_urn = xml_ns['default'] # check that our urn is mapped try: _ = get_urn_details(sidd_urn) check_schema = True except Exception as e: logger.exception('SIDD: The SIDD namespace has unrecognized value') check_schema = False valid_xml = None if check_schema: valid_xml = evaluate_xml_versus_schema(xml_string, sidd_urn) if valid_xml is None: valid_xml = True # perform the various sidd structure checks if sidd_urn == 'urn:SIDD:1.0.0': the_sidd = SIDDType1.from_node(root_node, xml_ns=xml_ns) valid_sidd_contents = the_sidd.is_valid(recursive=True, stack=False) elif sidd_urn == 'urn:SIDD:2.0.0': the_sidd = SIDDType2.from_node(root_node, xml_ns=xml_ns) valid_sidd_contents = the_sidd.is_valid(recursive=True, stack=False) else: raise ValueError('Got unhandled urn {}'.format(sidd_urn)) return valid_xml & valid_sidd_contents, sidd_urn, the_sidd
def _extract_crsd(self): """ Extract and interpret the CRSD structure from the file. """ xml = self.get_crsd_bytes() if self.crsd_version.startswith('1.0'): the_type = CRSDType else: raise ValueError(_unhandled_version_text.format(self.crsd_version)) root_node, xml_ns = parse_xml_from_string(xml) if 'default' in xml_ns: self._crsd_meta = the_type.from_node(root_node, xml_ns, ns_key='default') else: self._crsd_meta = the_type.from_node(root_node, xml_ns)
def _evaluate_xml_string_validity(xml_string): """ Check the validity of the SICD xml, as defined by the given string. Parameters ---------- xml_string : str|bytes Returns ------- (bool, str, SICDType) """ root_node, xml_ns = parse_xml_from_string(xml_string) if xml_ns is None: raise ValueError( 'SICD XML invalid, because no apparent namespace defined in the xml,\n\t' 'which starts `{}...`'.format(xml_string[:15])) if 'default' not in xml_ns: raise ValueError( 'Could not properly interpret the namespace collection from xml\n{}' .format(xml_ns)) sicd_urn = xml_ns['default'] # check that our urn is mapped try: _ = get_urn_details(sicd_urn) check_schema = True except Exception as e: logger.exception('SICD: The SICD namespace has unrecognized value') check_schema = False valid_xml = None if check_schema: valid_xml = evaluate_xml_versus_schema(xml_string, sicd_urn) if valid_xml is None: valid_xml = True # perform the various sicd structure checks the_sicd = SICDType.from_node(root_node, xml_ns=xml_ns) valid_sicd_contents = the_sicd.is_valid(recursive=True, stack=False) return valid_xml & valid_sicd_contents, sicd_urn, the_sicd
def get_sicd(self): """ Extract the SICD details. Returns ------- SICDType """ if self._sicd is not None: return self._sicd if self._user_data is None: self._read_user_data() if self._caspr_data is None: self._find_caspr_data() # Check if the user data contains a sicd structure. sicd_string = None for nam in ['SICDMETA', 'SICD_META', 'SICD']: if sicd_string is None: sicd_string = self._user_data.get(nam, None) # If so, assume that this SICD is valid and simply present it if sicd_string is not None: root_node, xml_ns = parse_xml_from_string(sicd_string) self._sicd = SICDType.from_node(root_node, xml_ns) self._sicd.derive() else: # otherwise, we populate a really minimal sicd structure num_rows, num_cols = self.data_size self._sicd = SICDType(ImageData=ImageDataType(NumRows=num_rows, NumCols=num_cols, FirstRow=0, FirstCol=0, PixelType=self.pixel_type, FullImage=FullImageType(NumRows=num_rows, NumCols=num_cols), SCPPixel=RowColType(Row=num_rows/2, Col=num_cols/2))) return self._sicd
def _find_sicd(self) -> None: self._is_sicd = False self._sicd_meta = None if self.des_subheader_offsets is None: return for i in range(self.des_subheader_offsets.size): subhead_bytes = self.get_des_subheader_bytes(i) if subhead_bytes.startswith(b'DEXML_DATA_CONTENT'): des_header = DataExtensionHeader.from_bytes(subhead_bytes, start=0) des_bytes = self.get_des_bytes(i) # noinspection PyBroadException try: root_node, xml_ns = parse_xml_from_string(des_bytes.decode('utf-8').strip().encode()) if 'SIDD' in root_node.tag: # namespace makes this ugly # NOTE that SIDD files are supposed to have the corresponding # SICD xml as one of the DES AFTER the SIDD xml. # The same basic format is used for both headers. # So, abandon if we find a SIDD xml self._des_index = None self._des_header = None self._is_sicd = False break elif 'SICD' in root_node.tag: # namespace makes this ugly self._des_index = i self._des_header = des_header self._is_sicd = True if xml_ns is None: self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key=None) else: self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key='default') break except Exception: continue elif subhead_bytes.startswith(b'DESIDD_XML'): # This is an old format SIDD and can't be a SICD self._des_index = None self._des_header = None self._is_sicd = False break elif subhead_bytes.startswith(b'DESICD_XML'): # This is an old format SICD des_bytes = self.get_des_bytes(i) try: root_node, xml_ns = parse_xml_from_string(des_bytes.decode('utf-8').strip().encode()) if 'SICD' in root_node.tag: # namespace makes this ugly self._des_index = i self._des_header = None self._is_sicd = True if xml_ns is None: self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key=None) else: self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key='default') break except Exception as e: logger.error( 'We found an apparent old-style SICD DES header,\n\t' 'but failed parsing with error {}'.format(e)) continue if not self._is_sicd: return # noinspection PyBroadException try: self._sicd_meta.derive() except Exception as e: pass