Skip to content

Instantly share code, notes, and snippets.

@gustavofonseca
Last active August 29, 2015 14:04
Show Gist options
  • Save gustavofonseca/e9d0656fd2c0e7f65393 to your computer and use it in GitHub Desktop.
Save gustavofonseca/e9d0656fd2c0e7f65393 to your computer and use it in GitHub Desktop.
def get_xpath(element):
"""Get the XPath string to element.
This code is a port of a C# snippet published at
http://stackoverflow.com/a/9221904
"""
path = '/' + element.tag
parent = element.getparent()
if parent is not None:
siblings = parent.findall(element.tag)
if len(siblings) > 1:
position = 1
for sibling in siblings:
if sibling is element:
break
else:
position += 1
path += '[%s]' % position
path = get_xpath(parent) + path
return path
import unittest
from StringIO import StringIO
from lxml import etree
class GetXpathTests(unittest.TestCase):
def test_root_level(self):
sample = StringIO("""
<article>
<front>
Hey!
</front>
</article>
""")
sample = etree.parse(sample)
element = sample.getroot()
self.assertEqual(utils.get_xpath(element), '/article')
def test_first_level(self):
sample = StringIO("""
<article>
<front>
Hey!
</front>
</article>
""")
sample = etree.parse(sample)
element = sample.xpath('front')[0]
resulting_xpath = utils.get_xpath(element)
self.assertEqual(resulting_xpath, '/article/front')
self.assertIn(element, sample.xpath(resulting_xpath))
def test_first_level_many(self):
sample = StringIO("""
<article>
<front>
Hey!
</front>
<front>
You!
</front>
</article>
""")
sample = etree.parse(sample)
element = sample.xpath('front')[1]
resulting_xpath = utils.get_xpath(element)
self.assertEqual(resulting_xpath, '/article/front[2]')
self.assertIn(element, sample.xpath(resulting_xpath))
def test_second_level(self):
sample = StringIO("""
<article>
<front>
Hey!
<title>
Foobar
</title>
</front>
</article>
""")
sample = etree.parse(sample)
element = sample.xpath('front/title')[0]
resulting_xpath = utils.get_xpath(element)
self.assertEqual(resulting_xpath, '/article/front/title')
self.assertIn(element, sample.xpath(resulting_xpath))
def test_first_level_many(self):
sample = StringIO("""
<article>
<front>
Hey!
</front>
<front>
You!
<title>
Foobar
</title>
<title title-type="actual">
Baz
</title>
</front>
</article>
""")
sample = etree.parse(sample)
element = sample.xpath('front/title[@title-type="actual"]')[0]
resulting_xpath = utils.get_xpath(element)
self.assertEqual(resulting_xpath, '/article/front[2]/title[2]')
self.assertIn(element, sample.xpath(resulting_xpath))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment