我有一个看起来像这个文件的KML(只有“文档”部分再重复2000次左右,每个条目的坐标略有不同)。
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
<Placemark>
<Polygon>
<extrude>1</extrude>
<tesselate>1</tesselate>
<altitudeMode>relativeToGround</altitudeMode>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-89.634425,40.73053,16
-89.633951,40.73053,16
-89.633951,40.73013,16
-89.634425,40.73013,16
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
<Style>
<PolyStyle>
<color>#5a14F000</color>
<outline>1</outline>
</PolyStyle>
</Style>
</Placemark>
<Document>
</kml>
该文件已从Google地球中导出。我正在尝试上传到映射工具(如CartoDB或Mapbox),但该文件因错误而被拒绝。我通过像这样的KML验证器运行文件:KMLValidator。我决定要上传的更改是:
1)将第2行替换为:
<kml xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2">
2)“关闭坐标”这意味着当前列出的坐标基本上是一个正方形(4个角),以满足验证器,我必须通过重复第一组坐标来关闭多边形。所以目标是:
<coordinates>
-89.634425,40.73053,16
-89.633951,40.73053,16
-89.633951,40.73013,16
-89.634425,40.73013,16
-89.634425,40.73053,16
</coordinates>
然而,我的问题是我无法以有效的方式更新坐标。到目前为止,这是我能想到的最好的(在this post的帮助下:
来自pykml导入解析器的来自os导入路径
from lxml import etree
kml_file = path.join( \
'C:\Development', \
'sample.kml')
# Source: https://stackoverflow.com/questions/13712132/extract-coordinates-from-kml-batchgeo-file-with-python
root = parser.fromstring(open(kml_file, 'r').read())
coordinates_before = root.Document.Placemark.Polygon.outerBoundaryIs.LinearRing.coordinates
# Print the coordinates (only prints the first branch )
print 'coordinates before'
print coordinates_before
# Set the coordinates to a new value - Attempting to update to new values
# Get Errors from this
root.Document.Placemark.Polygon.outerBoundaryIs.LinearRing.coordinates
= coordinates_before+"1,1,1"
coordinates_after = root.Document.Placemark.Polygon.outerBoundaryIs.LinearRing.coordinates
print 'coordinates after'
print coordinates_after
# # Create and store a string representation of full KML tree
root_string = etree.tostring(root, pretty_print=True)
# # # Print the string representation using pretty_print
print root_string
如您所见,我可以设法添加一组额外的值(1,1,1),但
a)我没有使用第一个坐标的值(而只是虚拟值)
b)它只更新第一个分支(如何将其缩放以重复另外2000次?
c)当我更新输出文件时也会显示此文本
"coordinates xmlns:py="http://codespeak.net/lxml/objectify/pytype" py:pytype="str">"
道歉,如果这是一个过于深入的问题,我一直在努力解决这个问题太久了,似乎应该有一个我想念的简单方法。在此先感谢您的帮助。
答案 0 :(得分:0)
回答了我自己的问题。感谢Jaron让我失意(虽然我最终没有使用正则表达式,而是使用Element Tree)。一旦我更熟悉在嵌套树中导航,我就设法弄明白了。还有助于更熟悉.findall()并在for子句中使用它。谢谢!
def close_the_polygons(kml_file,color_name):
# # Get the tree from KML File, add get color_name (only used when writing the file name )
tree = ET.parse(kml_file)
root = tree.getroot()
# iterate through tree to get to coordinate level
for Document in root:
for Placemark in Document.findall('Placemark'):
for Polygon in Placemark.findall('Polygon'):
for outerBoundaryIs in Polygon.findall('outerBoundaryIs'):
for LinearRing in outerBoundaryIs: # don't use Findall here because only 1 subelement
for coordinates in LinearRing: # don't use Findall here because only 1 subelement
### convert the co-ordinate to text and delimiters become ordinary text (i.e. repr)
coordinates_text_before = repr(coordinates.text)
# ## Split the text (identifying the delimters)
coordinates_split_before = coordinates_text_before.split("\\t")
# # Store each entry of the array
entry_1 = coordinates_split_before[1]
entry_2 = coordinates_split_before[2][2:]
entry_3 = coordinates_split_before[3][2:]
entry_4 = coordinates_split_before[4][2:-10]
entry_5 = entry_1 #this solves the underlying problem of closing the polygon
# # # consolidate into a single item array, goal with delimiters is to get it back to original text
string_updated_coordinates = "'\\n\\t"+entry_1+"\\t\\n"+entry_2+"\\t\\n"+entry_3+"\\t\\n"+entry_4+"\\t\\n"+entry_5+"\\n'"
updated_coordinates = literal_eval(string_updated_coordinates)
# # Store Updated Coordinates into original coordinates location
coordinates.text = updated_coordinates
# # Write back to a file once all updates are complete
tree = ET.ElementTree(root)
tree.write('new_data_%s_closedPolygon_v1.0.kml' %color_name, xml_declaration=True)
return