3

我有一个具有以下结构的巨大 kml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <Style id="transBluePoly">
      <LineStyle>
        <width>1.5</width>
      </LineStyle>
      <PolyStyle>
        <color>30ffa911</color>
      </PolyStyle>
    </Style>
    <Style id="labelStyle">
       <IconStyle>
          <color>ffffa911</color>
          <scale>0.35</scale>
       </IconStyle>
       <LabelStyle>
         <color>ffffffff</color>
         <scale>0.35</scale>
      </LabelStyle>
    </Style>
    <Placemark>
      <name>9840229084|2013-03-06 13:41:34.0|rent|0.0|2|0|0|1|T|5990F529FB98F28A1F17D182152201A4|0|null|null|null|null|null|null|null|null|null|null|F|F|0|NO_POSTCODE</name>
      <styleUrl>#transBluePoly</styleUrl>
      <Polygon>
        <outerBoundaryIs>
          <LinearRing>
            <coordinates>
            -1.5191200,53.4086600
            -1.5214300,53.4011900
            -1.5303600,53.4028800
            -1.5435800,53.4033900
            -1.5404900,53.4083600
            -1.5191200,53.4086600
            </coordinates>
          </LinearRing>
        </outerBoundaryIs>
      </Polygon>
    </Placemark>
    <Placemark>
      <name>9840031669|2013-03-06 13:14:22.0|rent|0.0|0|0|0|1|F|E5BAC836984F53F91D7F60F247920F0C|0|null|null|null|null|null|null|null|null|null|null|F|F|3641161|DE4 3JT</name>
      <styleUrl>#transBluePoly</styleUrl>
      <Polygon>
        <outerBoundaryIs>
          <LinearRing>
            <coordinates>
            -1.2370933,53.1227587
            -1.2304837,53.1690463
            -1.1783129,53.2226956
            -1.2016444,53.2833233
            -1.3213687,53.3248921
            -1.4809916,53.3039582
            -1.6167192,53.2438689
            -1.5593782,53.1336370
            -1.4296123,53.0962399
            -1.3205129,53.1024090
            -1.2370933,53.1227587
            </coordinates>
          </LinearRing>
        </outerBoundaryIs>
      </Polygon>
    </Placemark>

我需要从中提取 100 万个多边形以使其易于管理(知道 geo DB 是最终解决方案 - 寻找快速修复)。

将它加载到轻量级文本编辑器中并删除一些行将是我的第一个停靠点,但怀疑这将需要永远和一天的时间(它是 10 Gb,我有 16 Gb RAM)。只是想知道是否有来自 linux 终端的更智能的解决方案,可以避免将其全部读入 RAM。我已经看到 perl 和 bash 命令执行此操作,但看不到它们如何用于获取随机(或第一百万)样本:http ://www.unix.com/shell-programming-scripting/159470-filter -kml-file-xml-remove-unwanted-entries.html

4

3 回答 3

1

您可以使用 KML 解析库和几行代码来解析大型 KML 或 KMZ 文件中所需的内容。

爪哇

例如,GIScore Java 库使用 STaX 一次解析 KML 源文件一个特征,因此它不需要将整个文件加载到内存中。该库运行速度非常快,因此 10GB 不会花费很长时间。

这是一个简单的 Java 程序,它从 KML 文件中的多边形中提取点,无论 KML 文件有多大,也不管 Placemark 是否深深嵌套在文件夹中。

import org.opensextant.geodesy.Geodetic2DPoint;
import org.opensextant.giscore.events.*;
import org.opensextant.giscore.geometry.*;
import org.opensextant.giscore.input.kml.KmlInputStream;

import java.io.FileInputStream;
import java.io.IOException;
import java.text.DecimalFormat;

public class Test {

  public static void main(String[] args) throws IOException {
    KmlInputStream kis = new KmlInputStream(new FileInputStream("test.kml"));
    IGISObject obj;
    DecimalFormat df = new DecimalFormat("0.0#####");
    while((obj = kis.read()) != null) {
      if (obj instanceof Feature) {
        Feature f = (Feature)obj;
        Geometry g = f.getGeometry();
        if (g instanceof Polygon) {
          System.out.println("Points");
          for(Point p : ((Polygon)g).getOuterRing().getPoints()) {
            // do something with the points (e.g. insert in database, etc.)
            Geodetic2DPoint pt = p.asGeodetic2DPoint();
            System.out.printf("%s,%s%n",
                    df.format(pt.getLatitudeAsDegrees()),
                    df.format(pt.getLongitudeAsDegrees()));
          }
        }
      }
    }
    kis.close();
  }
}

要运行,在目录 src/main/java 中创建源文件 Test.java 并将上面的代码复制到文件中。

如果 Geometry 是MultiGeometry,那么您需要为此添加检查并迭代子几何。

使用 Gradle,这里有一个示例build.gradle脚本,使用以下命令运行上述测试程序:gradle run

apply plugin: 'java'

repositories {
    mavenCentral()
}

task run (dependsOn: 'compileJava', type: JavaExec) {
    main = 'Test'
    classpath = sourceSets.main.runtimeClasspath
}

dependencies {
    compile 'org.opensextant:geodesy:2.0.1'
    compile 'org.opensextant:giscore:2.0.1'
}

这确实需要您同时安装GradleJava 开发工具包(JDK)。

Python

或者,您可以使用 Python 和pykml库来解析 KML。可以使用一些逻辑创建多个较小的 KML 文件以分割多边形或将多边形几何特征插入 PostgreSQL 数据库等。stackoverflow 中使用标签支持 pykml。

from pykml import parser
import re

with open('data.kml', 'r') as fp:
  doc = parser.parse(fp)

for pm in doc.getroot().Document.Placemark:
  print(pm.name)
  # Get the coordinates from either polygon or polygon inside multigeometry
  if hasattr(pm, 'MultiGeometry'):
    pm = pm.MultiGeometry
  if hasattr(pm, 'Polygon'):
    pcoords = pm.Polygon.outerBoundaryIs.LinearRing.coordinates.text
    # extract coords into a list of lon,lat coord pairs
    coords = re.split(r'\s+', pcoords.strip())
    for coord in coords:
        lonlat = coord.split(',')
        if len(lonlat) > 1:
            print(lonlat[0], lonlat[1])
            # add logic here - insert points into DB, etc.
于 2015-06-29T16:44:25.060 回答
0

这可能为时已晚,但对您有一些想法。

传统上,我使用通配符搜索在 Microsoft Word 中修改了此类代码块。虽然您的文件对于 Word 来说可能太大,但这些概念可以与其他类似工具一起使用。

我取了你文件的一个块并执行了三个搜索和替换 (1) 以获取名称并将其插入 " 标记中,(2) 删除中间字符块并将它们替换为 = char 和 (3) 到删除最后的代码块。

它是这样工作的:

(我实际上做了一些整理以首先删除空格 - 这些可能是本网站的人工制品,而不是代码本身)

Replace  [<]Placemark[>][<]name[>](**)[<]/name[>]   by   “\1”

Replace  [<]styleUrl(**)[<]coordinates[>]             by   =

Replace  [<]/coordinates(**)[<]Placemark[>]         by   nothing

使用一些字符作为转义符需要方括号来停止单词(我可能经常使用它们?)

(**) 序列捕获这些组之间的所有内容,并为它们提供用于替换字段的标签 \1。

从理论上讲,您应该能够将这三个一起使用,但这会给 Word 带来过于复杂的表单错误,直到您回到基础并减少代码。所以:

Replace [<]Place**name[>](**)[<]/name**nates[>](**)[<]/coord**mark[>] by "\1"=\3

实际上会起作用。

当然,您可以轻松地将结果的格式更改为您想要的格式(即不在输出中使用 " 或 = ),并使用进一步的搜索和替换,您可以操纵输出,为您想要的任何包做好准备。

通配符搜索和替换很有趣!

鲍勃·J。

PS 我使用这个概念在 Word vba 中编写了一个编译器,从 Excel 中获取一系列文本字符串,这些字符串包含基本的映射数据并将它们转换为完全可操作的 kml 文件。当前输入文件超过 2500 行超过 200k 个字符,并生成一个 700k kml 文件,分布在近 19,000 行上。“编译”大约需要 30 秒。这与你的情况相反。

于 2013-05-06T23:19:37.363 回答
-2

我有点晚了,但这个答案可能会对某人有所帮助。您可以使用 FME DESKTOP 这个巨大的软件完美地分割 kml 文件!使用 ModuloCount 转换器。检查拆分 kml 文件 ModuloCount

于 2017-05-06T15:44:03.927 回答