2

The following is a little OSM Overpass API example with PHP SimpleXML I've compiled The first part shows how you can query an Overpass Endpoint with standard PHP.

For you the second part is more interesting. That is querying the XML data you have already. This is most easily done with xpath, the used PHP XML library is based on libxml which supports XPath 1.0 which covers the various querying needs very well. The following example lists all schools and tries to obtain their names as well.

<?php
/**
 * OSM Overpass API with PHP SimpleXML / XPath
 *
 * PHP Version: 5.4 - Can be back-ported to 5.3 by using 5.3 Array-Syntax (not PHP 5.4's square brackets)
 */
//
// 1.) Query an OSM Overpass API Endpoint
//

$query = 'node
  ["amenity"~".*"]
  (-54.5247541978, 2.05338918702, 9.56001631027, 51.1485061713);
out;';

$context = stream_context_create(['http' => [
    'method'  => 'POST',
    'header' => ['Content-Type: application/x-www-form-urlencoded'],
    'content' => 'data=' . urlencode($query),
]]);

$endpoint = 'http://overpass-api.de/api/interpreter';
libxml_set_streams_context($context);
$start = microtime(true);

$result = simplexml_load_file($endpoint);
printf("Query returned %2\$d node(s) and took %1\$.5f seconds.\n\n", microtime(true) - $start, count($result->node));

//
// 2.) Work with the XML Result
//

# get all school nodes with xpath
$xpath = '//node[tag[@k = "amenity" and @v = "school"]]';
$schools = $result->xpath($xpath);
printf("%d School(s) found:\n", count($schools));
foreach ($schools as $index => $school)
{
# Get the name of the school (if any), again with xpath
list($name) = $school->xpath('tag[@k = "name"]/@v') + ['(unnamed)'];
list($website) = $school->xpath('tag[@k = "website"]/@v') + ['(no website)'];
list($email) = $school->xpath('tag[@k = "contact:email"]/@v') + ['(no email)'];
printf("#%02d: ID:%' -10s  [%s,%s]  %s %s %s\n", $index, $school['id'], $school['lat'], $school['lon'], $name, $website, $email);
}


//node[tag[@k = "amenity" and @v = "school"]]
//tag[@k = "name"]/@v'

$query = 'node
  ["addr:postcode"~"RM12"]
  (51.5557914,0.2118915,51.5673083,0.2369398);
   node
  (around:1000)
  ["amenity"~"fast_food"];
           out;';

$context = stream_context_create(['http' => [
    'method'  => 'POST',
    'header' => ['Content-Type: application/x-www-form-urlencoded'],
    'content' => 'data=' . urlencode($query),
]]);

$endpoint = 'http://overpass-api.de/api/interpreter';
libxml_set_streams_context($context);

$result = simplexml_load_file($endpoint);
printf("Query returned %2\$d node(s) and took %1\$.5f seconds.\n\n", microtime(true) - $start, count($result->node));

see the results:

#37106: ID:5240594723  [-1.5819917,31.1314383]  St.Peter Claver (no website) (no email)
#37107: ID:5240600022  [-1.5844517,31.1350983]  Bugene primary school (no website) (no email)
#37108: ID:5240600123  [-1.5828800,31.1360933]  Bugene secondary school (no website) (no email)
#37109: ID:5240712123  [-1.6709812,31.1231337]  Bisheshe primary school (no website) (no email)
#37110: ID:5240722122  [-1.5902096,31.1435042]  Nyakahanga primary school (no website) (no email)
#37111: ID:5240726625  [-1.7424469,31.1186092]  Ruhinda seco school (no website) (no email)
#37112: ID:5240751236  [-1.7526170,31.1164731]  Nyaishozi primary (no website) (no email)
#37113: ID:5240765825  [-1.7510750,31.1141233]  Nyaishozi  Sec School (no website) (no email)
#37114: ID:5240769524  [-1.6866387,31.1125302]  Rwandaro primary school (no website) (no email)
#37115: ID:5240840021  [-18.9137094,47.5680227]  (unnamed) (no website) (no email)
#37116: ID:5241020221  [-1.5192416,31.1547499]  KATEMPRIS Primary School (no website) (no email)
#37117: ID:5241034821  [-1.4372971,31.1813319]  Maguge Primary School (no website) (no email)

see the following code that takes care for the parsing..:

# Get the name of the school (if any), again with xpath
list($name) = $school->xpath('tag[@k = "name"]/@v') + ['(unnamed)'];
list($website) = $school->xpath('tag[@k = "website"]/@v') + ['(no website)'];
list($email) = $school->xpath('tag[@k = "contact:email"]/@v') + ['(no email)'];
printf("#%02d: ID:%' -10s  [%s,%s]  %s %s %s\n", $index, $school['id'], $school['lat'], $school['lon'], $name, $website, $email);
}

guess that i have to look for some alternative tagging-shemes.

closed as unclear what you're asking by MaryBeth, aldo_tapia, whyzar, xunilk, Mark Ireland Feb 15 '18 at 20:41

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    What exactly is your question? Why do you query all amenity=* in a huge bounding box, only to filter out amenity=school in a post processing step. This is extremely inefficient. Use [amenity=school] as filter criterion in your overpass query instead! – mmd Feb 15 '18 at 18:56

Browse other questions tagged or ask your own question.