title: python, lxml or etree to get a parent of a node containing some text
body: <p>how can i proceed to get the parent node of a node containing a piece of text?</p>
  
  <p>moreover can i use some regexp mecanism as the matched element for searching/filtering, below searching from <code>re.compile("th[ei]s? .ne")</code> for example?</p>
  
  <p>say <code>this one</code></p>
  
  <pre><code>html = '''&lt;html&gt;
  &lt;head&gt;&lt;title&gt;&lt;/title&gt;&lt;/head&gt;
  &lt;body&gt;
  &lt;table&gt;
  &lt;tr&gt;&lt;td&gt;1a&lt;/td&gt;&lt;td&gt;2a&lt;/td&gt;&lt;td&gt;3a&lt;/td&gt;&lt;td&gt;4a&lt;/td&gt;&lt;td&gt;5a&lt;/td&gt;&lt;td&gt;6a&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1b&lt;/td&gt;&lt;td&gt;2b&lt;/td&gt;&lt;td&gt;3b&lt;/td&gt;&lt;td&gt;4b&lt;/td&gt;&lt;td&gt;5b&lt;/td&gt;&lt;td&gt;6b&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1c&lt;/td&gt;&lt;td&gt;2c&lt;/td&gt;&lt;td&gt;3c&lt;/td&gt;&lt;td&gt;4c&lt;/td&gt;&lt;td&gt;5c&lt;/td&gt;&lt;td&gt;6c this one&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
  &lt;div&gt;&lt;div&gt;
  &lt;table&gt;
  &lt;tr&gt;&lt;td&gt;1A&lt;/td&gt;&lt;td&gt;2A&lt;/td&gt;&lt;td&gt;3A&lt;/td&gt;&lt;td&gt;4A&lt;/td&gt;&lt;td&gt;5A&lt;/td&gt;&lt;td&gt;6A&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1B&lt;/td&gt;&lt;td&gt;2B&lt;/td&gt;&lt;td&gt;3B&lt;/td&gt;&lt;td&gt;4B&lt;/td&gt;&lt;td&gt;5B&lt;/td&gt;&lt;td&gt;6B&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1C&lt;/td&gt;&lt;td&gt;2C&lt;/td&gt;&lt;td&gt;3C&lt;/td&gt;&lt;td&gt;4C&lt;/td&gt;&lt;td&gt;5C&lt;/td&gt;&lt;td&gt;6C&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;this one
  &lt;/div&gt;&lt;/div&gt;
  &lt;/body&gt;
  &lt;/html&gt;'''
  </code></pre>
  
  <p>i would like to have an iterator that return:</p>
  
  <pre><code>&lt;td&gt;6c this one&lt;/td&gt;
  </code></pre>
  
  <p>and then:</p>
  
  <pre><code>&lt;div&gt;
  &lt;table&gt;
  &lt;tr&gt;&lt;td&gt;1A&lt;/td&gt;&lt;td&gt;2A&lt;/td&gt;&lt;td&gt;3A&lt;/td&gt;&lt;td&gt;4A&lt;/td&gt;&lt;td&gt;5A&lt;/td&gt;&lt;td&gt;6A&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1B&lt;/td&gt;&lt;td&gt;2B&lt;/td&gt;&lt;td&gt;3B&lt;/td&gt;&lt;td&gt;4B&lt;/td&gt;&lt;td&gt;5B&lt;/td&gt;&lt;td&gt;6B&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1C&lt;/td&gt;&lt;td&gt;2C&lt;/td&gt;&lt;td&gt;3C&lt;/td&gt;&lt;td&gt;4C&lt;/td&gt;&lt;td&gt;5C&lt;/td&gt;&lt;td&gt;6C&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;this one
  &lt;/div&gt;
  </code></pre>
  
  <p>i tried:</p>
  
  <pre><code>import lxml.html
  root = lxml.html.document_fromstring(html)
  root.xpath("//text()[contains(., one)]")
  </code></pre>
  
  <p>and </p>
  
  <pre><code>import xml.etree.ElementTree as ET
  for e in ET.fromstring(html).getiterator():
      if e.text and e.text.find('one') != -1:
          print "Found string %r, element = %r" % (e.text, e)
  </code></pre>
  
  <p>but the best i can have is the node containing <code>this one</code> itself... while i am looking for the parent containing this text. notice that div or table are only for example, i really need to go backward to the parent after finding "this one" rather than filtering xml element containing <code>this one</code> because i will not know that this is a div, a table or anything before finding what it contains.</p>
  
  <p>(notice also that it is html and not well formated xml, as i suppose que the second <code>this one</code> should have been wrapped in a xml tag)</p>
  
  <p>EDIT:</p>
  
  <pre><code>&gt;&gt;&gt; root.xpath("//*[contains(child::*/text(), 'one')]") # why empty parent?
  []
  &gt;&gt;&gt; root.xpath("//*[contains(text(), 'one')]") # i expected to have a list with two elements td and div
  [&lt;Element td at 0x280b600&gt;]
  &gt;&gt;&gt; root.xpath("//*[child::*[contains(text(), 'one')]]") # if parent: expected tr and div, if not parent expected table or div, still missing one
  [&lt;Element tr at 0x2821f30&gt;]
  </code></pre>
  
  <p>BTW, using the last is ok:</p>
  
  <pre><code>import xml.etree.ElementTree as ET
  import lxml.html
  #[... here add html = """...]
  root = lxml.html.document_fromstring(html)
  for i, x in enumerate(root.xpath("//text()[contains(., 'one')]/parent::*")):
      print "%s =&gt; \n\t" % i, ET.tostring(x).replace("\n", "\n\t")
  </code></pre>
  
  <p>produce:</p>
  
  <pre><code>0 =&gt; 
      &lt;td&gt;6c this one&lt;/td&gt;
  1 =&gt; 
      &lt;div&gt;
      &lt;table&gt;
      &lt;tr&gt;&lt;td&gt;1A&lt;/td&gt;&lt;td&gt;2A&lt;/td&gt;&lt;td&gt;3A&lt;/td&gt;&lt;td&gt;4A&lt;/td&gt;&lt;td&gt;5A&lt;/td&gt;&lt;td&gt;6A&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;1B&lt;/td&gt;&lt;td&gt;2B&lt;/td&gt;&lt;td&gt;3B&lt;/td&gt;&lt;td&gt;4B&lt;/td&gt;&lt;td&gt;5B&lt;/td&gt;&lt;td&gt;6B&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;1C&lt;/td&gt;&lt;td&gt;2C&lt;/td&gt;&lt;td&gt;3C&lt;/td&gt;&lt;td&gt;4C&lt;/td&gt;&lt;td&gt;5C&lt;/td&gt;&lt;td&gt;6C&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;this one
      &lt;/div&gt;
  </code></pre>