1

我有一个看起来像这个文件的 KML(只有“文档”部分再重复 2,000 次左右,每个条目中的坐标略有不同)。

<?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>

但是,我的问题是我无法以有效的方式更新坐标。到目前为止,这是我能想到的最好的(在这篇文章的帮助下:

从 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)它只更新第一个分支(我如何扩展它以重复另外 2,000 次?

c)当我更新输出文件时也会显示此文本

 "coordinates xmlns:py="http://codespeak.net/lxml/objectify/pytype" py:pytype="str">"

如果这是一个过于深入的问题,我深表歉意,我已经为此苦苦挣扎了太久,似乎应该有一种我想念的简单方法。提前感谢您的帮助。

4

1 回答 1

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
于 2016-06-16T21:18:47.763 回答