【问题标题】:How to use R's xpathApply to extract kml coordinates and put them in a dataframe如何使用 R 的 xpathApply 提取 kml 坐标并将它们放入数据框中
【发布时间】: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 文件并从中提取坐标?

标签: xml r xpath kml


【解决方案1】:

只是实现@Gavin 的优秀建议:(假设文件名为map.kml)。

library(rgdal)

setwd("<directory containing kml file>")

system(paste("ogrinfo", "map.kml")) # diagnostic to identify the layers
# Had to open data source read-only.
# INFO: Open of `map.kml'
#       using driver `KML' successful.
# 1: KmlFile (Line String)          <- This is the layer name

map <- readOGR(dsn="map.kml",layer="KmlFile")
df  <- data.frame(map@lines[[1]]@Lines[[1]]@coords)
colnames(df) <- c("lon","lat")
df

#         lon      lat
# 1  4.538678 43.96218
# 2  4.536100 43.96221
# 3  4.537710 43.96415
# 4  4.536106 43.96536
# 5  4.538665 43.96604
# ...

一些注意事项:

  1. readOGR(...) 的 KML 驱动程序需要文件名(可选的路径)作为 dsn,并且 kml 名称标签的文本作为层。开头的系统调用标识层。

  2. readOGR(...) 抛出 z 维度。因此,如果您需要,这种方法将不适合您。

  3. 坐标的位置取决于几何形状和元素的数量。在您的情况下,您只有一条路径。

  4. 您的文件中实际上存在错误,位于第 2 行(xmlns:gx 命名空间声明中缺少右引号)。您需要修复它,否则文件将无法导入..

【讨论】:

  • 我复制了你的实现,效果很好。
猜你喜欢
  • 2021-10-17
  • 1970-01-01
  • 2019-07-09
  • 1970-01-01
  • 1970-01-01
  • 2019-07-30
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
相关资源
最近更新 更多