def _xpath(self, xpath_str, tree=None, first=False, history=False, cast=False, **kwargs): if tree is None: tree = self.tree logger.debug(xpath_str) elements = tree.xpath( xpath_str, namespaces={'re': 'http://exslt.org/regular-expressions'} ) res = [] for e in elements: if history or e.getparent().tag != 'History': if cast: if e.tag == 'Entry': res.append(Entry(element=e, kp=self)) elif e.tag == 'Group': res.append(Group(element=e, kp=self)) elif e.tag == 'Binary' and e.getparent().tag == 'Entry': res.append(Attachment(element=e, kp=self)) else: raise Exception('Could not cast element {}'.format(e)) else: res.append(e) # return first object in list or None if first: res = res[0] if res else None return res
def _xpath(self, xpath_str, tree=None, first=False, history=False, cast=False, **kwargs): """Look up elements in the XML payload and return corresponding object. Internal function which searches the payload lxml ElementTree for elements via XPath. Matched entry, group, and attachment elements are automatically cast to their corresponding objects, otherwise an error is raised. Args: xpath_str (str): XPath query for finding element(s) tree (:obj:`_ElementTree`, :obj:`Element`, optional): use this element as root node when searching first (bool): If True, function returns first result or None. If False, function returns list of matches or empty list. Default is False. history (bool): If True, history entries are included in results. Default is False. cast (bool): If True, matches are instead instantiated as pykeepass Group, Entry, or Attachment objects. An exception is raised if a match cannot be cast. Default is False. """ if tree is None: tree = self.tree logger.debug(xpath_str) elements = tree.xpath( xpath_str, namespaces={'re': 'http://exslt.org/regular-expressions'}) res = [] for e in elements: if history or e.getparent().tag != 'History': if cast: if e.tag == 'Entry': res.append(Entry(element=e, kp=self)) elif e.tag == 'Group': res.append(Group(element=e, kp=self)) elif e.tag == 'Binary' and e.getparent().tag == 'Entry': res.append(Attachment(element=e, kp=self)) else: raise Exception('Could not cast element {}'.format(e)) else: res.append(e) # return first object in list or None if first: res = res[0] if res else None return res