拆分一个巨大的kml文件

时间:2013-04-16 21:11:16

标签: kml

我有一个巨大的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

3 个答案:

答案 0 :(得分:1)

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

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

这是一个简单的Java程序,它从KML文件中的多边形中提取点,这与KML文件的大小无关,也不会将地标深深嵌套在文件夹中。

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 Development Kit(JDK)。

答案 1 :(得分:0)

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

我传统上使用Wild卡搜索在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

实际上会有效。

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

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

Bob J。

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

答案 2 :(得分:-2)

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