docs: def Read(self, meta_only=False, allowed=None, cast=False):
          """Read the ESPA XML metadata file"""
          if allowed is not None and not isinstance(allowed, (list, tuple)):
              raise RuntimeError('`allowed` must be a list of str names.')
  
          meta = xmltodict.parse(
                  open(self.filename, 'r').read()
              ).get('espa_metadata')
  
          # Handle bands seperately
          bands = meta.get('bands').get('band')
          del(meta['bands'])
  
          if not isinstance(bands, (list)):
              bands = [bands]
          meta = self.CleanDict(meta)
  
          # Get spatial refernce
          ras = SetProperties(RasterSet, meta)
  
          if allowed is not None:
              # Remove non-allowed arrays from bdict
              for k in list(self.bdict.keys()):
                  if k not in allowed:
                      del(self.bdict[k])
  
          for i in range(len(bands)):
              info = self.GenerateBand(bands[i], meta_only=True, cast=cast)
              if allowed is not None and info.name not in allowed:
                  continue
              if info.name not in self.bdict.keys() or self.bdict[info.name].data is None:
                  b = self.GenerateBand(bands[i], meta_only=meta_only, cast=cast)
                  self.bdict[b.name] = b
              elif cast and self.bdict[info.name].data.dtype != np.float32:
                  b = self.GenerateBand(bands[i], meta_only=meta_only, cast=cast)
                  self.bdict[b.name] = b
              elif not cast and self.bdict[info.name].data.dtype == np.float32:
                  b = self.GenerateBand(bands[i], meta_only=meta_only, cast=cast)
                  self.bdict[b.name] = b
          ras.bands = self.bdict
  
          if not meta_only:
              ras.validate()
  
          return ras