Complex search in xml using lxml
<p><strong>Background</strong> I am trying to read a password from a keepass2 file using <a href="https://github.com/phpwutz/libkeepass" rel="nofollow">libkeepass</a> python library.</p>

<p>Using <a href="http://lxml.de/" rel="nofollow">lxml</a> (beause that is what libkeepass gives me) I have to search for an entry like this and take the password value from it</p>

<pre><code>&lt;Entry&gt;
&lt;String&gt;
    &lt;Key&gt;Password&lt;/Key&gt;
    &lt;Value Protected="False" ProtectedValue="XXX"&gt;XXX&lt;/Value&gt;
&lt;/String&gt;
&lt;String&gt;
    &lt;Key&gt;Title&lt;/Key&gt;
    &lt;Value&gt;PasswordName&lt;/Value&gt;
&lt;/Entry&gt;
</code></pre>

<p>So I have to find an entry:</p>

<ul>
<li>with a child "String"

<ul>
<li>with a child "Key" with value "Title"</li>
<li>with a child "Value" with value "PasswordName"</li>
</ul></li>
<li>with a child "String"

<ul>
<li>with a child "Key" with value "Password"</li>
<li>with a child "Value" -> and the value of that child is what I need</li>
</ul></li>
</ul>

<p>I already got this far (kdb beeing the password file object):</p>

<pre><code>kdb.obj_root.findall(".//Entry/String[Key='Title'][Value='PasswordName']")
</code></pre>

<p>This gives me the String Element of the correct entry.</p>

<p>Alternatively, instead of going down to <code>String</code>, back up to <code>Entry</code> and then down again to another <code>String</code>, you can just use predicate on <code>Entry</code> element and then return the target <code>String</code> element from there. </p>

<p>Since you're using <code>lxml</code>, I'd also suggest to use <code>xpath()</code> method instead of <code>findall()</code>. The former provides full support for XPath 1.0 expression, while the latter only supports <a href="https://docs.python.org/2/library/xml.etree.elementtree.html#elementtree-xpath" rel="nofollow">subset of XPath 1.0</a> :</p>

<pre><code>query = """
        .//Entry[String[Key='Title' and Value='MyPassword']]
         /String[Key='Password']
         /Value
        """
kdb.obj_root.xpath(query)
</code></pre>

python lxml