【问题标题】:How to update a KML to include a new Element with a value如何更新 KML 以包含具有值的新元素
【发布时间】:2019-04-13 23:51:45
【问题描述】:

我的 KML 在元素地标下没有元素“名称”。因此,使用 Google 地球打开 KML 时,树下的每个多边形旁边都没有名称。

在下面的原始 kml 中,有 2 个 Placemark。每个都有一个元素 simpleData name="ID"。与它们相关的 2 个值分别是 FM2 和 FM3。

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" 
xmlns:gx="http://www.google.com/kml/ext/2.2" 
xmlns:kml="http://www.opengis.net/kml/2.2" 
xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
    <name>Test.kml</name>
    <open>1</open>
    <Schema name="test" id="S_test_SSSSSIIIDSDDDDDISSSDSSSDD">
        <SimpleField type="string" name="ID"> <displayName>&lt;b&gt;ID&lt;/b&gt;</displayName>
    </SimpleField>
    <SimpleField type="string" name="cname"><displayName>&lt;b&gt;cname&lt;/b&gt;</displayName>
    </SimpleField>
    </Schema>
    <Style id="falseColor01">
        <BalloonStyle>
            <text><![CDATA[<table border="0"><tr> 
            <td>b>ID</b>/td>td>$[test/ID]</td></tr>
            <tr><td><b>cname</b></td><td>$[test/cname]</td></tr>
            </table>]]></text>
        </BalloonStyle>
        <LineStyle>
            <color>ffffff00</color>
            <width>3</width>
        </LineStyle>
        <PolyStyle>
            <color>ffffff00</color>
            <colorMode>random</colorMode>
            <fill>0</fill>
        </PolyStyle>
    </Style>
    <StyleMap id="falseColor0">
        <Pair>
            <key>normal</key>
            <styleUrl>#falseColor00</styleUrl>
        </Pair>
        <Pair>
            <key>highlight</key>
            <styleUrl>#falseColor01</styleUrl>
       </Pair>
    </StyleMap>
    <Style id="falseColor00">
      <BalloonStyle>   
      </BalloonStyle>
        <LineStyle>
            <color>ffffff00</color>
            <width>3</width>
        </LineStyle>
        <PolyStyle>
            <color>ffffff00</color>
            <colorMode>random</colorMode>
            <fill>0</fill>
        </PolyStyle>
    </Style>
    <Folder id="layer 0">
        <name>Test_1</name>
        <open>1</open>
        <Placemark>
            <styleUrl>#falseColor0</styleUrl>
            <ExtendedData>
                <SchemaData schemaUrl="#S_test_SSSSSIIIDSDDDDDISSSDSSSDD">
                    <SimpleData name="ID">FM2</SimpleData>
                    <SimpleData name="cname">FM2</SimpleData>
                </SchemaData>
            </ExtendedData>
            <Polygon>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>150.889999,-32.17281600000001,0 
                        </coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>
        </Placemark>
        <Placemark>
            <styleUrl>#falseColor0</styleUrl>
            <ExtendedData>
                <SchemaData schemaUrl="#S_test_SSSSSIIIDSDDDDDISSSDSSSDD">
                    <SimpleData name="ID">FM3</SimpleData>
                    <SimpleData name="cname">FM3</SimpleData>
                </SchemaData>
            </ExtendedData>
            <Polygon>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>150.90104,-32.15662800000001,0
                        </coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>
        </Placemark>
    </Folder>
</Document>
</kml>

在@DanielHaley 的帮助下,我能够读取元素值 FM2 和 FM3。

How to obtain Element values from a KML by using lmxl

然后我尝试使用 lxml etree 教程在每个元素下添加一个元素“名称”,其值分别为“FM2”和“FM3”。我没有运气。

这是我期望得到的:

    <Folder id="layer 0">
        <name>Test_1</name>
        <open>1</open>
        <Placemark>
            <name>FM2</name>
            <styleUrl>#falseColor0</styleUrl>
            <ExtendedData>
                <SchemaData schemaUrl="#S_test_SSSSSIIIDSDDDDDISSSDSSSDD">
                    <SimpleData name="ID">FM2</SimpleData>
                    <SimpleData name="cname">FM2</SimpleData>
                </SchemaData>
            </ExtendedData>
            <Polygon>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>150.889999,-32.17281600000001,0 
                        </coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>
        </Placemark>
        <Placemark>
            <name>FM3</name>
            <styleUrl>#falseColor0</styleUrl>
            <ExtendedData>
                <SchemaData schemaUrl="#S_test_SSSSSIIIDSDDDDDISSSDSSSDD">
                    <SimpleData name="ID">FM3</SimpleData>
                    <SimpleData name="cname">FM3</SimpleData>
                </SchemaData>
            </ExtendedData>
            <Polygon>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>150.90104,-32.15662800000001,0
                        </coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>
        </Placemark>
    </Folder>

谁能给我一个提示?

如果可能的话,您能否请您稍微解释一下命名空间的概念?我查看了谷歌的教程,但解释不是很完整。

【问题讨论】:

    标签: python lxml kml


    【解决方案1】:

    如果要修改Placemark,请先选择它。

    然后创建新的name 元素并从SimpleData 中提取值以用作它的文本值。

    最后将新元素插入Placemark

    示例...

    Python

    from lxml import etree
    
    ns = {"kml": "http://www.opengis.net/kml/2.2"}
    
    # Using a parser to improve formatting of new "name" elements
    # and, most importantly, to preserve CDATA sections.
    parser = etree.XMLParser(remove_blank_text=True, strip_cdata=False)
    
    tree = etree.parse("test.kml", parser=parser)
    
    for placemark in tree.xpath("//kml:Placemark", namespaces=ns):
        # Create new "name" element in kml namespace ({http://www.opengis.net/kml/2.2}name).
        name_element = etree.Element(etree.QName(ns.get("kml"), "name"), nsmap=ns)
    
        # Set value of "name" element to value from SimpleData.
        name_element.text = placemark.xpath("kml:ExtendedData/kml:SchemaData/kml:SimpleData[@name='ID']/text()",
                                            namespaces=ns)[0]
    
        # Insert the new element into "placemark" as the first child.
        placemark.insert(0, name_element)
    
    print(etree.tostring(tree, pretty_print=True).decode("UTF-8"))
    

    打印的 XML 输出

    <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
      <Document>
        <name>Test.kml</name>
        <open>1</open>
        <Schema name="test" id="S_test_SSSSSIIIDSDDDDDISSSDSSSDD">
          <SimpleField type="string" name="ID">
            <displayName>&lt;b&gt;ID&lt;/b&gt;</displayName>
          </SimpleField>
          <SimpleField type="string" name="cname">
            <displayName>&lt;b&gt;cname&lt;/b&gt;</displayName>
          </SimpleField>
        </Schema>
        <Style id="falseColor01">
          <BalloonStyle>
            <text><![CDATA[<table border="0"><tr> 
                <td>b>ID</b>/td>td>$[test/ID]</td></tr>
                <tr><td><b>cname</b></td><td>$[test/cname]</td></tr>
                </table>]]></text>
          </BalloonStyle>
          <LineStyle>
            <color>ffffff00</color>
            <width>3</width>
          </LineStyle>
          <PolyStyle>
            <color>ffffff00</color>
            <colorMode>random</colorMode>
            <fill>0</fill>
          </PolyStyle>
        </Style>
        <StyleMap id="falseColor0">
          <Pair>
            <key>normal</key>
            <styleUrl>#falseColor00</styleUrl>
          </Pair>
          <Pair>
            <key>highlight</key>
            <styleUrl>#falseColor01</styleUrl>
          </Pair>
        </StyleMap>
        <Style id="falseColor00">
          <BalloonStyle>   
                </BalloonStyle>
          <LineStyle>
            <color>ffffff00</color>
            <width>3</width>
          </LineStyle>
          <PolyStyle>
            <color>ffffff00</color>
            <colorMode>random</colorMode>
            <fill>0</fill>
          </PolyStyle>
        </Style>
        <Folder id="layer 0">
          <name>Test_1</name>
          <open>1</open>
          <Placemark>
            <name>FM2</name>
            <styleUrl>#falseColor0</styleUrl>
            <ExtendedData>
              <SchemaData schemaUrl="#S_test_SSSSSIIIDSDDDDDISSSDSSSDD">
                <SimpleData name="ID">FM2</SimpleData>
                <SimpleData name="cname">FM2</SimpleData>
              </SchemaData>
            </ExtendedData>
            <Polygon>
              <outerBoundaryIs>
                <LinearRing>
                  <coordinates>150.889999,-32.17281600000001,0 
                                </coordinates>
                </LinearRing>
              </outerBoundaryIs>
            </Polygon>
          </Placemark>
          <Placemark>
            <name>FM3</name>
            <styleUrl>#falseColor0</styleUrl>
            <ExtendedData>
              <SchemaData schemaUrl="#S_test_SSSSSIIIDSDDDDDISSSDSSSDD">
                <SimpleData name="ID">FM3</SimpleData>
                <SimpleData name="cname">FM3</SimpleData>
              </SchemaData>
            </ExtendedData>
            <Polygon>
              <outerBoundaryIs>
                <LinearRing>
                  <coordinates>150.90104,-32.15662800000001,0
                                </coordinates>
                </LinearRing>
              </outerBoundaryIs>
            </Polygon>
          </Placemark>
        </Folder>
      </Document>
    </kml>
    

    另外,see here 了解有关 XML 命名空间的更多信息。它比我在这里做得更好。

    【讨论】:

    • 完美答案。 @丹尼尔。非常感激。学到了很多。
    • 我试图保存输出。我使用的是 csv.write,看来这不是一个好的选择。保存输出的最有效方法是什么?
    • 哦...看起来很简单。我刚刚尝试了 tree.write 并且它有效。
    • @Marlin - 在 ElementTree 对象上使用 write()...tree.write("new_file.kml", pretty_print=True)
    猜你喜欢
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-19
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多