1

Minimal example:

In [1]: from lxml import etree

In [2]: etree.fromstring('<who>syslogd</who>').xpath('/who/text()')

Out[2]: ['syslogd']

currently I'm using helper function:

def safe_xpath_one(tree: Element, xpath: str) -> Union[Element, None]:
    res = tree.xpath(xpath)
    if res:
        return res[0]

Here I then need to check first element from result which is additional. Is there direct way of specifying that I want the first and only first element?

P.S.: I think I got too much used to bs4's soup.select_one

Rahul
  • 10,830
  • 4
  • 53
  • 88
  • https://stackoverflow.com/questions/12615366/getting-exactly-one-element-or-raising-exception-with-lxml-xpath is there but again, I don't want to raise and handle error. It should return result or None – Rahul Dec 10 '22 at 13:24
  • You want the same example of that answer but without throw exception? – Jaky Ruby Dec 10 '22 at 13:28
  • Kind of. Yes. Just wanted to make sure if we have tree.xpath_one similiar to soup.select_one. – Rahul Dec 10 '22 at 13:29

2 Answers2

0

To get the first element from an lxml object using xpath, you can use the [0] index operator after your xpath query. For example, if you have an lxml object called root, you could use the following code to get the first element matching the xpath query //p:

first_element = root.xpath('//p')[0]

This would return the first p element in the lxml object.

Another way to get the first element matching an xpath query is to use the find() method instead of xpath(). For example, you could use the following code to get the first p element in the lxml object:

first_element = root.find('//p')

This will return the first element that matches the xpath query, rather than returning a list of matching elements. You can then access the element's properties and attributes using standard dot notation, like so:

print (first_element.text)
rajnikant7008
  • 76
  • 2
  • 10
0

I don't know if this is the answer but, this is how I'm currently doing

from lxml import etree
from functools import partial

def get_xpath_one(tree, xpath):
    res = tree.xpath(xpath)
    if res:
        return res[0]

tree = etree.fromstring('<who>syslogd</who>')
xpath_one = partial(get_xpath_one, tree)
res = xpath_one('/who/text()')

Out: 'syslogd'
Rahul
  • 10,830
  • 4
  • 53
  • 88