IronMan12
IronMan12

Reputation: 11

Parsing XML with Python and etree

I want to extract all the way elements that contain a tag with the key 'highway' and a specific value from the following example Open Street Map XML file:

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="CGImap 0.0.2">
 <bounds minlat="54.0889580" minlon="12.2487570" maxlat="54.0913900" maxlon="12.2524800"/>

 <node id="298884272" lat="54.0901447" lon="12.2516513" user="SvenHRO" uid="46882" visible="true" version="1" changeset="676636" timestamp="2008-09-21T21:37:45Z"/>
 <way id="26659127" user="Masch" uid="55988" visible="true" version="5" changeset="4142606" timestamp="2010-03-16T11:47:08Z">
  <nd ref="292403538"/>
  <nd ref="298884289"/>

  <nd ref="261728686"/>
  <tag k="highway" v="unclassified"/>
  <tag k="name" v="Pastower Straße"/>
 </way>
 <relation id="56688" user="kmvar" uid="56190" visible="true" version="28" changeset="6947637" timestamp="2011-01-12T14:23:49Z">
  <member type="node" ref="294942404" role=""/>
  ...
  <member type="node" ref="364933006" role=""/>
  <member type="way" ref="4579143" role=""/>
  ...
  <member type="node" ref="249673494" role=""/>
  <tag k="name" v="Küstenbus Linie 123"/>
  <tag k="network" v="VVW"/>
  <tag k="operator" v="Regionalverkehr Küste"/>
  <tag k="ref" v="123"/>
  <tag k="route" v="bus"/>
  <tag k="type" v="route"/>
 </relation>

</osm>

To do this; I wrote the following piece of Python code that uses the Etree library. It parses the XML document and uses the findall function (with XPath syntax)

import xml.etree.ElementTree as ET
supported_highways = ('motorway', 'trunk', 'primary', 'secondary', 'tertiary', 'unclassified', 'residential', 'highway_link', 'trunk_link', 'primary_link', 'secondary_link', 'tertiary_link')

class OSMParser:

    def __init__(self, inputData):
        self.root = ET.fromstring(inputData)


    def getRoads(self):
        ways = dict()
        for road in self.root.findall('./way/'):
            highway_tags = road.findall("./tag[@k='highway']")
            if not highway_tags:
                continue
            if all(highway.attrib['v'] not in supported_highways for highway in highway_tags):
                continue

However when I run the code, it does not find tag of the way element (the second findall produces an empty list). Any idea what's wrong? Thank you.

Upvotes: 0

Views: 543

Answers (2)

Vivek Sable
Vivek Sable

Reputation: 10213

Its working.

>>> root.findall("./way/tag[@k='highway']")
[<Element 'tag' at 0xb74568ac>]

I think in your input content tag way is not child of main start tag i.e. root tag.

or use lxml.etree

>>> import lxml.etree as ET1
>>> root = ET1.fromstring(content)
>>> root.xpath("//way/tag[@k='highway']")
[<Element tag at 0xb745642c>]

Upvotes: 0

user1907906
user1907906

Reputation:

Try the XPath //way/ instead of ./way/.

Upvotes: 1

Related Questions