从另一个写入 KML 文件

Write KML file from another

我正在努力:

- read a KML file
- remove the Placemark element if name = 'ZONE'
- write a new KML file without the element

这是我的代码:

from pykml import parser
kml_file_path = '../Source/Lombardia.kml'

removeList = list()

with open(kml_file_path) as f:
 folder = parser.parse(f).getroot().Document.Folder

for pm in folder.Placemark:
    if pm.name == 'ZONE':
        removeList.append(pm)
        print pm.name

for tag in removeList:
    parent = tag.getparent()
    parent.remove(tag)
#Write the new file
#I cannot reach the solution help me

这是 KML:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
    <name>Lombardia</name>
    <Style>
    ...
    </Style>
    <Folder>
<Placemark>
            <name>ZOGNO</name>
            <styleUrl>#FEATURES_LABELS</styleUrl>
            <Point>
                <coordinates>9.680530595139061,45.7941656233647,0</coordinates>
            </Point>
        </Placemark>
        <Placemark>
            <name>ZONE</name>
            <styleUrl>#FEATURES_LABELS</styleUrl>
            <Point>
                <coordinates>10.1315885854064,45.7592449779275,0</coordinates>
            </Point>
        </Placemark>
    </Folder>
</Document>
</kml>

问题是,当我编写新的 KML 文件时,它仍然有我要删除的元素。 事实上,我想删除包含 name = ZONE 的元素。 我做错了什么? 谢谢。

--- 最终代码 感谢@Dawid Ferenczy,这是工作代码:

from lxml import etree
import pykml
from pykml import parser

kml_file_path = '../Source/Lombardia.kml'

# parse the input file into an object tree
with open(kml_file_path) as f:
  tree = parser.parse(f)

# get a reference to the "Document.Folder" node
folder = tree.getroot().Document.Folder

# iterate through all "Document.Folder.Placemark" nodes and find and remove all nodes
# which contain child node "name" with content "ZONE"
for pm in folder.Placemark:
    if pm.name == 'ZOGNO':
        parent = pm.getparent()
        parent.remove(pm)

# convert the object tree into a string and write it into an output file
with open('output.kml', 'w') as output:
    output.write(etree.tostring(folder, pretty_print=True))

您的代码中存在以下问题:

  • 您没有将整个解析的对象树存储在任何地方(您只有对节点“Document.Folder”的引用:folder = parser.parse(f).getroot().Document.Folder)但是你想把它写回一个文件,所以你需要存储它
  • 我不明白为什么你需要两个循环和列表 removeList 当你可以在第一个循环中直接删除元素时
  • 你没有阅读文档 - 在 pykml 库的文档 examples 下很好地描述了如何将对象树写入文件

试试下面的代码:

from lxml import etree
from pykml import parser

kml_file_path = './input.kml'

# parse the input file into an object tree
with open(kml_file_path) as f:
  tree = parser.parse(f)

# get a reference to the "Document.Folder" node
folder = tree.getroot().Document.Folder

# iterate through all "Document.Folder.Placemark" nodes and find and remove all nodes 
# which contain child node "name" with content "ZONE"
for pm in folder.Placemark:
    if pm.name == 'ZONE':
        parent = pm.getparent()
        parent.remove(pm)

# convert the object tree into a string and write it into an output file
with open('output.kml', 'w') as output:
    output.write(etree.tostring(tree, pretty_print=True))

很简单:

  • KML 文件被解析为对象树并存储在变量 tree
  • 直接操作同一个对象树(去掉元素)
  • 相同的对象树被写回文件

考虑一下 XSLT,设计用于转换 XML 文件的专用语言。并且因为 KML 文件 XML 文件,所以这个解决方案是可行的。 Python 的第三方模块 lxml 可以 运行 XSLT 1.0 脚本,并且无需循环即可执行此操作。

具体来说,XSLT 脚本 运行s Identity Transform 可以按原样复制整个文档。然后,脚本 运行 在元素上创建一个空模板(以特定逻辑为条件)以删除该元素。为了适应默认命名空间,前缀 doc 用于 XPath 搜索。

XSLT (另存为.xsl文件,特殊的.xml文件在下面Python加载)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:doc="http://earth.google.com/kml/2.2">
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="doc:Placemark[doc:name='ZONE']"/>

</xsl:stylesheet>

XSLT Fiddle Demo

Python

import lxml.etree as et

# LOAD XML AND XSL
doc = et.parse('/path/to/Input.xml')
xsl = et.parse('/path/to/XSLT_Script.xsl')

# CONFIGURE TRANSFORMER
transform = et.XSLT(xsl)    

# RUN TRANSFORMATION
result = transform(doc)

# PRINT RESULT
print(result)  

# SAVE TO FILE
with open('output.xml', 'wb') as f:
   f.write(result)

输出

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
   <Document>
      <name>Lombardia</name>
      <Style>
    ...
    </Style>
      <Folder>
         <Placemark>
            <name>ZOGNO</name>
            <styleUrl>#FEATURES_LABELS</styleUrl>
            <Point>
               <coordinates>9.680530595139061,45.7941656233647,0</coordinates>
            </Point>
         </Placemark>
      </Folder>
   </Document>
</kml>