XPath - Selecting preceding and following sibling of a specific node in a single query

python, xml, xpath

Solution

If you are using lxml (which currently only supports XPath version 1.0), you have to spell out each XPath entirely, and join them with `|`:

'''/osm/way/nd[@ref=203936110]/following-sibling::nd[1] 
   | /osm/way/nd[@ref=203936110]/preceding-sibling::nd[1]'''

For example,

import lxml.etree as ET
content = '''\
<record>
    <nd>First</nd>
    <nd>Second</nd>
    <nd ref="203936110"></nd>
    <nd>Third</nd>
    <nd>Fourth</nd>    
</record>'''
root = ET.fromstring(content)

for elt in root.xpath('''
    //nd[@ref="203936110"]/following-sibling::nd[1]
    |
    //nd[@ref="203936110"]/preceding-sibling::nd[1]'''):

    print(elt.text)

yields

Second
Third

Problem

I'm currently working with Open Street Maps data and I'm trying to select the preceding and following sibling of a specific node. My queries currently look like this : ``` /osm/way/nd[@ref=203936110]/following-sibling::nd[1] /osm/way/nd[@ref=203936110]/preceding-sibling::nd[1] ``` These queries work as expected but I'd like to merge them into a single query. I did found some examples mentioning that this is possible but for some reason I haven't been able to find the right syntax to make it work. This query, for example, is invalid : ``` /osm/way/nd[@ref=203936110]/(following-sibling::nd[1] or preceding-sibling::nd[1]) ```

Original source

Related problems