code: def _fix_value(self, value):
          
          if not self.__charrange or not self.__replacement:
              if sys.maxunicode == 0xFFFF:
                  # Fix for python 2.x, surrogate pairs does not match in regex
                  self.__charrange = re.compile(
                      u'^([\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD]|[\uD800-\uDBFF][\uDC00-\uDFFF])*$')
                  # TODO: this regex is slightly wrong... surrogates are not matched as pairs.
                  self.__replacement = re.compile(u'[^\u0020-\uDBFF\u0009\u000A\u000D\uE000-\uFFFD\uDC00-\uDFFF]')
              else:
                  self.__charrange = re.compile(u'^[\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]*$')
                  self.__replacement = re.compile(u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]')
  
          # Reading string until \x00. This is the same as aapt does.
          if "\x00" in value:
              self.packerwarning = True
              log.warning(
                  "Null byte found in attribute value at position {}: "
                  "Value(hex): '{}'".format(
                      value.find("\x00"),
                      binascii.hexlify(value.encode("utf-8"))
                  )
              )
              value = value[:value.find("\x00")]
  
          if not self.__charrange.match(value):
              log.warning("Invalid character in value found. Replacing with '_'.")
              self.packerwarning = True
              value = self.__replacement.sub('_', value)
          return value
docs: Return a cleaned version of a value
          according to the specification:
          > Char	   ::=   	#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
  
          See https://www.w3.org/TR/xml/#charsets
  
          :param value: a value to clean
          :return: the cleaned value