以下是用PHP的SimpleXML一点OSM立交桥API的例子,我已经编译,因为我们没有在这里为PHP和我爱OSM,让我们来展示一些有用的例子。
第一部分显示了如何使用标准PHP查询立交桥端点。你不需要的部分,因为你已经保存在您硬盘中的数据:
<?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"~".*"]
(38.415938460513274,16.06338500976562,39.52205163048525,17.51220703125);
out;';
$context = stream_context_create(['http' => [
'method' => 'POST',
'header' => ['Content-Type: application/x-www-form-urlencoded'],
'content' => 'data=' . urlencode($query),
]]);
# please do not stress this service, this example is for demonstration purposes only.
$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));
对于你的第二个部分是更有趣。这就是查询你已有的XML数据。这很容易用xpath完成,所用的PHP XML库基于libxml,它支持XPath 1.0,它很好地覆盖了各种查询需求。
以下示例列出了所有学校,并尝试获取其名称。我还没有介绍的翻译还没有,因为我的样本数据没有这些,但是你也可以看看所有类型的名称,包括翻译,只是喜欢一个特定的一个):
//
// 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)'];
printf("#%02d: ID:%' -10s [%s,%s] %s\n", $index, $school['id'], $school['lat'], $school['lon'], $name);
}
这里的关键点是XPath的查询。使用两个,第一个获得具有特定标签的节点。我觉得这是最有趣的一个给你:
//node[tag[@k = "amenity" and @v = "school"]]
此行说:给我说有一个标签元素的所有节点元素中它具有ķ属性值“舒适”和v属性值“学校”。这是你必须过滤那些标记为设施学校的节点的条件。
而且XPath的再次使用,现在相对于那些学校的节点,看看是否有一个名字,如果是把它牵回家:
tag[@k = "name"]/@v'
此行说:相对于当前节点,给我v属性来自标签元素作为k属性值“名称”。正如你所看到的,一些零件再次与之前的生产线类似。我认为你们都可以采纳他们来满足你的需求。
因为不是所有的学校节点有一个名字,默认的字符串是通过将其添加到(当时空的)结果阵列提供用于显示目的:
list($name) = $school->xpath('tag[@k = "name"]/@v') + ['(unnamed)'];
^^^^^^^^^^^^^^^
Provide Default Value
所以在这里我的结果对于代码 - 例如:
Query returned 907 node(s) and took 1.10735 seconds.
10 School(s) found:
#00: ID:332534486 [39.5017565,16.2721899] Scuola Primaria
#01: ID:1428094278 [39.3320912,16.1862820] (unnamed)
#02: ID:1822746784 [38.9075566,16.5776597] (unnamed)
#03: ID:1822755951 [38.9120272,16.5713431] (unnamed)
#04: ID:1903859699 [38.6830409,16.5522243] Liceo Scientifico Statale A. Guarasci
#05: ID:2002566438 [39.1347698,16.0736924] (unnamed)
#06: ID:2056891127 [39.4106679,16.8254844] (unnamed)
#07: ID:2056892999 [39.4124687,16.8286119] (unnamed)
#08: ID:2272010226 [39.4481717,16.2894353] SCUOLA DELL'INFANZIA SAN FRANCESCO
#09: ID:2272017152 [39.4502366,16.2807664] SCUOLA MEDIA
我希望这已经有用了,如果您有更多的澄清问题,请告诉我。
(由rbwilkinson):这是你如何可以添加额外的参数,以找到其他值。下面的例子中找到一公里范围内的其他属性:
$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));
}
你坚持在看什么部分的过程中,有什么不为你工作?当Google搜寻'php parse osm'(当然,'php parse xml')时,我会看到一些有趣的链接。为什么不先查看那些? – 2013-04-21 08:12:17
我开始制作我自己的XML解析器,但我对XML不太熟悉。我坚持循环遍历节点,只得到父节点。 – palAlaa 2013-04-21 08:16:07
@palAlaa:请问您如何使用PHP来显示问题。然后我们可以给你一些提示和/或给你一个答案。否则你的描述有点宽泛,我会猜测你遇到困难以及如何解决问题。 – hakre 2013-04-21 08:43:17