I'd like to open a USGS KML file of bedrock geology for an entire county, but there are over 2,000 individual polygon layers. Does anyone know if there is a way to merge all of these layers together into one file before opening in QGIS?
-
2Your initial statement is a bit confusing. Do you have one kml file with multiple polygons in it, or do you have 2000 individual kml files representing the bedrock geology types?– Get SpatialJul 22, 2012 at 20:31
-
1One thing you might do is use python and the QGIS API to do it. This question and answer provides a means to get started: How to write standalone Python scripts using QGIS– Get SpatialJul 22, 2012 at 20:32
-
Yes it is one kml file with multiple polygon files. I was hoping for a plugin, because I know nothing about programming with python, but maybe now is a good time to start learning! Thanks.– PatrickJul 23, 2012 at 15:55
-
1I am not sure I understand, if I have a kml file with multiple lines, that would just open as one layer with multiple lines in QGIS. If on the other hand you have multiple kml files, you can open them all in Google earth, put them in one folder and export the folder as a new kml.– EcodivAug 1, 2012 at 7:38
-
It seems foolish/dangerous to try to include all the files in one uber-file. A pain to process, and likely to cause crashing.– MoxApr 25, 2019 at 23:15
5 Answers
Here a simple shell script ("ogr_kml_merge.sh") which uses ogr2ogr:
#!/bin/sh
# Markus Neteler, 2008
# merge KML files
PROG=`basename $0`
if [ $# -lt 1 ] ; then
echo "Merges KML files together (mosaik)"
echo "Usage:"
echo " $PROG *.kml"
echo " $PROG a.kml b.kml c.kml"
echo "At then end of the merge you can select a new name"
exit 1
fi
LIST="$@"
OUT=file_merged
rm -f $OUT.kml
ogr2ogr -f KML $OUT.kml $1
shift
for i in `seq 1 $#` ; do
echo "Appending #$i: $1"
ogr2ogr -f KML -update -append $OUT.kml $1 -nln $OUT `basename $1 .kml`
shift
done
echo "Written: $OUT.kml"
echo -n "Enter file name for new KML (or CTRL-C): "
read NEW
NEW=`basename $NEW .kml`
mv $OUT.kml $NEW.kml
echo "Written as: $NEW.kml"
Hope this gives the idea.
-
Tried it, but I get:
ERROR 1: Unable to open existing output datasource file_merged.kml
– toklandFeb 3, 2017 at 12:17
One option would be to write a "wrapper" KML file and include links to each file in the wrapper, using the KML NetworkLink. Although it says "network", the Link element can contain a local file path instead. You can also use this in a KMZ structure
Create a folder in which you'll then add the individual kml/kmz files. Go to Save as and in your destination, save this folder as a kml.Your result will be a single kml file. Hope this helps
With the plug in MMQGIS is possible to merge to many .kml files into one only shape file once you have uploaded all of you .kml files in Q-GIS.
To install the MMQGIS, simply you have to go to the plugin bottom, and select in manage sources and plugin.
Once the plugin is installed, go to combine, and after merge layers. Done!
I assume that the issue is not that there are multiple files, but there is a single KML/KMZ with lots of folders that is loading as individual layers, which is generally unsuitable for manipulation and performance. You can see why this would be a problem:
Given that you asked how to merge all these layers together before opening in QGIS, there are two approaches:
Quick solution: Use KML Merger, an online tool located at https://kmlmerger.com/. Do note that you'll have to feed it two KML files, so you might need to create a KML with no data present, or create a dummy KML with one element of your original data set, then delete that element in the exported file. This can easily be done with a text editor.
Automated solution: Try this Python script to flatten XML files. It does read the KML line by line as if it were text, so it may not work on some valid KML files.
"""kmlflatten.py: reads a KML file as text, and strips out all Folder tags except the first and last. usage: python kmlflatten.py IN [OUT]"""
import os
import sys
if len(sys.argv) >= 2:
kmlfilein = sys.argv[1]
if len(sys.argv) >= 3:
kmlfileout = sys.argv[2]
else:
dotext = kmlfilein[kmlfilein.rfind(os.extsep):]
fname, ext = os.splitext(kmlfilein)
kmlfileout = fname + '_flattened' + ext
else:
kmlfilein = 'doc.kml'
kmlfileout = 'doc_flattened.kml'
with open(kmlfilein, 'r') as fi:
with open(kmlfileout, 'w') as fo:
folder, skip = False, False
for line in fi.readlines():
stline = line.strip() #remove indents, but hang onto original line.
if not folder: #copy up to first <Folder> tag
if stline == '<Folder>':
folder, skip = True, True
fo.write(line) # write the first folder!
else:
fo.write(line)
if folder: #copy lines except for the <Folder> tags and the <name> tag immediately proceeding
if skip:
skip = False
elif stline == '</Document>':
fo.write('\t</Folder>\n</Document>\n') # make sure to write the last </Folder> before done
elif stline == '<Folder>':
skip = True
elif stline == '</Folder>':
pass
else:
fo.write(line)
A more suitable solution would be to use an XML parsing library to move all Placemark
nodes into the first Folder
, and perhaps first save any data about the Folder
(like order or name) into the Placemark
feature itself before it's destroyed.