code: def get_failing_line(xml_string, exc_msg):
      
      max_before = 500  # max characters before reported position
      max_after = 500  # max characters after reported position
      max_unknown = 1000  # max characters when position cannot be determined
      assert isinstance(xml_string, six.binary_type)
      m = re.search(r':(\d+):(\d+):', exc_msg)
      if not m:
          xml_string, _ = truncate_line(xml_string, 1, 0, max_unknown - 1)
          return None, None, None, xml_string
      lineno = int(m.group(1))
      colno = int(m.group(2))
      if not xml_string.endswith(b'\n'):
          xml_string += b'\n'
      xml_lines = xml_string.splitlines()
      if len(xml_lines) < lineno:
          # This really should not happen; it means the line parsing went wrong
          # or SAX reported incorrect lines. We do not particularly care for
          # this case and simply truncate the string.
          xml_string, _ = truncate_line(xml_string, 1, 0, max_unknown - 1)
          return None, None, None, xml_string
      line = xml_lines[lineno - 1]
      line, new_pos = truncate_line(line, colno, max_before, max_after)
      return lineno, colno, new_pos, line
docs: Extract the failing line from the XML string, as indicated by the
      line/column information in the exception message.
  
      Returns a tuple (lineno, colno, new_pos, line), where lineno and colno
      and marker_pos may be None.