python - 如何更新 KML 以包含具有值的新元素

标签 python lxml kml

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

在下面的原始kml中,有2个地标。每个都有一个 Element 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>

有人可以给我提示吗?

如果可以的话,您能否解释一下命名空间的概念?我查看了 Google 的教程,但解释不太完整。

最佳答案

如果您想修改地标,请先选择它。

然后创建新的 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 命名空间的更多信息。它比我在这里能更好地解释。

关于python - 如何更新 KML 以包含具有值的新元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55670854/

相关文章:

python - 向 csr_matrix 添加元素的正确方法是什么?

Python XPath 抓取显示列表没有文本属性

google-maps - Google map 中的 KML 气球高度样式

python - 在 Ninja IDE 上导入 Python 模块时遇到问题

python - sympy 矩阵真的那么慢吗?

python - Python Pandas : read_html and python3-lxml installation 的问题

python - lxml xpath 找不到 anchor 文本

google-maps - Google map 和 KML 能否支持大于 32x32 的图标?

java - 将大 KML 文件加载到 Google map 中

python - 如何从 Anaconda 环境构建 .exe 程序 (Python 3.7)