【发布时间】:2013-12-29 04:39:35
【问题描述】:
我在 google earth 中创建了一个路径,然后使用以下说明复制并粘贴了 kml 文件(https://developers.google.com/kml/faq#validation - 如何创建 KML 文件?)
使用 R 的 xml 包我使用 xmlInternalTreeParse 没有问题:
doc2<-xmlInternalTreeParse("ROUTE_3.kml")
但这就是我尝试使用 xpathApply 时得到的结果:
xpathApply(doc2,"/kml//coordinates",xmlValue)
list()
我去掉kml标签的属性后,得到如下:
xpathApply(doc2,"/kml//coordinates",xmlValue)
[[1]]
[1] "4.538678046760991,43.96218242485241,0 4.536099605055323,43.96220903572051,0
4.53771014982657,43.96415063050954,0 4.536106012183452,43.96535632643623,0
4.538664824256699,43.9660402294286,0 4.539486616025195,43.96777930035288,0
4.54165951159373,43.96623221715382,0 4.543909553814832,43.96588360581748,0
4.541906820403621,43.96447824521096,0 4.543519784610379,43.96288529313735,0
4.540449258644572,43.9633940089841,0 4.544185719673153,43.9516337999984,0
4.536212701406948,43.94157791460842,0 4.539125112498221,43.96125976359349,0"
我使用 http://www.kmlvalidator.com/home.htm 检查了原始的 kml 文件,它说该文件“有效并符合最佳实践”。我是 xpath 的新手(通常是 xml,所以任何关于如何使用 kml 标签属性处理这个问题的建议都将不胜感激。
现在我将坐标作为列表的一个元素,是否有一种巧妙的方法可以制作一个以 lon lat elv 作为列标题的三列数据框? 我尝试了以下方法,但我确信有更好的方法(感谢:Split column at delimiter in data frame):如果您有更直接的解决方案,请告诉我。谢谢。
ll<-xpathApply(doc2,"/kml//coordinates",xmlValue)
s<-ll[[1]]
ss<-strsplit(s,split=" ")
df <- data.frame(do.call('rbind', strsplit(as.character(ss[[1]]),',',fixed=TRUE)))
colnames(df)<-c("lon", "lat", "elv")
df
lon lat elv
1 4.538678046760991 43.96218242485241 0
2 4.536099605055323 43.96220903572051 0
3 4.53771014982657 43.96415063050954 0
4 4.536106012183452 43.96535632643623 0
5 4.538664824256699 43.9660402294286 0
6 4.539486616025195 43.96777930035288 0
7 4.54165951159373 43.96623221715382 0
8 4.543909553814832 43.96588360581748 0
9 4.541906820403621 43.96447824521096 0
10 4.543519784610379 43.96288529313735 0
11 4.540449258644572 43.9633940089841 0
12 4.544185719673153 43.9516337999984 0
13 4.536212701406948 43.94157791460842 0
14 4.539125112498221 43.96125976359349 0
这是原始的 kml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
<name>KmlFile</name>
<StyleMap id="m_ylw-pushpin">
<Pair>
<key>normal</key>
<styleUrl>#s_ylw-pushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#s_ylw-pushpin_hl</styleUrl>
</Pair>
</StyleMap>
<Style id="s_ylw-pushpin">
<IconStyle>
<scale>1.1</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
</Style>
<Style id="s_ylw-pushpin_hl">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
</Style>
<Placemark>
<name>ROUTE_3</name>
<styleUrl>#m_ylw-pushpin</styleUrl>
<LineString>
<tessellate>1</tessellate>
<coordinates>
4.538678046760991,43.96218242485241,0
4.536099605055323,43.96220903572051,0
4.53771014982657,43.96415063050954,0
4.536106012183452,43.96535632643623,0
4.538664824256699,43.9660402294286,0
4.539486616025195,43.96777930035288,0
4.54165951159373,43.96623221715382,0
4.543909553814832,43.96588360581748,0
4.541906820403621,43.96447824521096,0
4.543519784610379,43.96288529313735,0
4.540449258644572,43.9633940089841,0
4.544185719673153,43.9516337999984,0
4.536212701406948,43.94157791460842,0
4.539125112498221,43.96125976359349,0
</coordinates>
</LineString>
</Placemark>
</Document>
</kml>
更新:在阅读了更多内容之后。特别是 XML 包文档部分,标题为 - 在内部 XML 树/DOM 中查找匹配节点 - 详细信息。我现在知道 kml 标记属性处理命名空间,所以我将 xpathApply 更正为:
xpathApply(doc2,"/kml:kml//kml:coordinates",xmlValue)
请注意,路径现在包含 kml: 命名空间。
现在我可以不加修改地使用 kml 文件。这是一个包装在函数中的示例:
library(XML)
KML_geo_path_coordinates_to_dataframe<-function(kml_file){
#this requires the xml library
doc2<-xmlInternalTreeParse(kml_file)
#the namespace issue (kml:) is explained in the getNodeSet(XML) R documentation under Details
ll<-xpathApply(doc2,"/kml:kml//kml:coordinates",xmlValue)
# ll delivers a list, I take the element I need out...a long string of coordinates separated by " "
s<-ll[[1]]
#however it may need some clean up
s<-gsub(pattern="\t",replacement="",x=s)
s<-gsub(pattern="\n",replacement="",x=s)
#split out the coordinate sets lon, lat, elv
ss<-strsplit(s,split=" ")
df <- data.frame(do.call('rbind', strsplit(as.character(ss[[1]]),',',fixed=TRUE)))
colnames(df)<-c("lon", "lat", "elv")
return(df)
}
【问题讨论】:
-
为什么不使用 R 中的空间包之一读取 kml 文件并从中提取坐标?