Python 使用lxml编辑KML的内容

Python 使用lxml编辑KML的内容,python,lxml,kml,Python,Lxml,Kml,我有一个简单的KML文件,我想使用etree.XMLParser修改它 <kml xmlns="http://www.opengis.net/kml/2.2"> <Document id="root_doc"> <Schema name="test" id="test"> <SimpleField name="id" type="string"/> <SimpleField name="LAT" typ

我有一个简单的KML文件,我想使用etree.XMLParser修改它

<kml xmlns="http://www.opengis.net/kml/2.2">
<Document id="root_doc">
    <Schema name="test" id="test">
        <SimpleField name="id" type="string"/>
        <SimpleField name="LAT" type="float"/>
        <SimpleField name="LONG" type="float"/>
    </Schema>
    <Folder>
        <name>test</name>
        <Placemark>
            <Style>
                <LineStyle><color>ff0000ff</color></LineStyle>
                <PolyStyle><fill>0</fill></PolyStyle>
            </Style>
            <ExtendedData>
            <SchemaData schemaUrl="#test">
                <SimpleData name="id">ABC</SimpleData>
                <SimpleData name="LAT">-35.06111</SimpleData>
                <SimpleData name="LONG">138.58389</SimpleData>
                </SchemaData>
            </ExtendedData>
            <Polygon>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>138.58389,-35.06111 138.585208,-35.059241 
                        </coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>
        </Placemark>
    </Folder>
</Document>
</kml>
其次,我想为文档插入一种新样式。我想创建一个字符串和一个字符串元素。在文档下插入字符串\u元素:

style_element = etree.Element(etree.QName(ns.get("kml"), "style"), nsmap=ns)
style_element.text = style_str   

document_element = tree.xpath("//kml:Document", namespaces=ns) 
document_element.insert(1, style_str)    
这是我想要的最终输出:

<kml xmlns="http://www.opengis.net/kml/2.2">
<Document id="root_doc">
    <Schema name="test" id="test_1">
        <SimpleField name="id" type="string"/>
        <SimpleField name="LAT" type="float"/>
        <SimpleField name="LONG" type="float"/>
    </Schema>
    <Style id="falseColor">
        <BalloonStyle>
            <text><![CDATA[<table border="0">
                <tr><td><b>ID</b></td><td>$[test/id]</td></tr>
                <tr><td><b>LAT</b></td><td>$[test/LAT]</td></tr>
                <tr><td><b>LON</b></td><td>$[test/LONG]</td></tr>
                </table>]]> 
            </text>
        </BalloonStyle>
        <PolyStyle>
            <colorMode>random</colorMode>
        </PolyStyle>
    </Style>
    <Folder>
        <name>test</name>
        <Placemark>
            <styleUrl>#falseColor</styleUrl>
            <ExtendedData>
                <SchemaData schemaUrl="#test_1">
                    <SimpleData name="id">ABC</SimpleData>
                    <SimpleData name="LAT">-35.06111</SimpleData>
                    <SimpleData name="LONG">138.58389</SimpleData>
                </SchemaData>
            </ExtendedData>
            <Polygon>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>138.58389,-35.06111 138.585208,-35.059241 
                        </coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>
        </Placemark>
    </Folder>
</Document>
</kml>

ID$[测试/ID]
拉脱维亚元[测试/拉脱维亚]
LON$[测试/长]
]]> 
随机的
测试
#假彩色
基础知识
-35.06111
138.58389
138.58389,-35.06111 138.585208,-35.059241 
有人能帮忙吗


谢谢第1部分:
schemaUrl
是一个属性。找到属性所属的元素并设置新值:

schemadata_element = tree.xpath("//kml:SchemaData", namespaces=ns)[0]
schemadata_element.set("schemaUrl", "#test_1")
Schema
元素上的
id
属性以相同的方式更新

第2部分:添加新样式有点棘手,但不是很难。将
样式
元素创建为字符串,通过
fromstring()
将其解析为
元素
对象(确保使用
strip\u CDATA=False
解析器选项保留CDATA节),然后将元素插入正确的位置

完成完成这两部分的代码(并删除现有的
Style
元素):

从lxml导入etree
ns={“kml”:http://www.opengis.net/kml/2.2"}
parser=etree.XMLParser(删除\u blank\u text=True,删除\u cdata=False)
tree=etree.parse(“your_kml_file.xml”,parser)
schema_element=tree.xpath(“//kml:schema”,名称空间=ns)[0]
schema_元素集(“id”,“test_1”)
schemadata_element=tree.xpath(“//kml:schemadata”,名称空间=ns)[0]
schemadata_element.set(“schemaUrl”,“test_1”)
#删除现有的“Style”元素并添加“styleUrl”元素
old_style_element=tree.xpath(“//kml:style”,名称空间=ns)[0]
placemark=old\u style\u元素。getparent()
placemark.remove(旧样式元素)
styleurl_element=etree.element(etree.QName(ns[“kml”],“styleurl”))
styleurl_element.text=“#falseColor”
placemark.insert(0,styleurl\u元素)
#添加新的“样式”元素
style_str=”“”
ID$[测试/ID]
拉脱维亚元[测试/拉脱维亚]
LON$[测试/长]
]]> 
随机的
"""
style\u元素=etree.fromstring(style\u str,解析器)
document\u element=tree.xpath(“//kml:document”,名称空间=ns)[0]
文档元素。插入(1,样式元素)

第1部分:
schemaUrl
是一个属性。找到属性所属的元素并设置新值:

schemadata_element = tree.xpath("//kml:SchemaData", namespaces=ns)[0]
schemadata_element.set("schemaUrl", "#test_1")
Schema
元素上的
id
属性以相同的方式更新

第2部分:添加新样式有点棘手,但不是很难。将
样式
元素创建为字符串,通过
fromstring()
将其解析为
元素
对象(确保使用
strip\u CDATA=False
解析器选项保留CDATA节),然后将元素插入正确的位置

完成完成这两部分的代码(并删除现有的
Style
元素):

从lxml导入etree
ns={“kml”:http://www.opengis.net/kml/2.2"}
parser=etree.XMLParser(删除\u blank\u text=True,删除\u cdata=False)
tree=etree.parse(“your_kml_file.xml”,parser)
schema_element=tree.xpath(“//kml:schema”,名称空间=ns)[0]
schema_元素集(“id”,“test_1”)
schemadata_element=tree.xpath(“//kml:schemadata”,名称空间=ns)[0]
schemadata_element.set(“schemaUrl”,“test_1”)
#删除现有的“Style”元素并添加“styleUrl”元素
old_style_element=tree.xpath(“//kml:style”,名称空间=ns)[0]
placemark=old\u style\u元素。getparent()
placemark.remove(旧样式元素)
styleurl_element=etree.element(etree.QName(ns[“kml”],“styleurl”))
styleurl_element.text=“#falseColor”
placemark.insert(0,styleurl\u元素)
#添加新的“样式”元素
style_str=”“”
ID$[测试/ID]
拉脱维亚元[测试/拉脱维亚]
LON$[测试/长]
]]> 
随机的
"""
style\u元素=etree.fromstring(style\u str,解析器)
document\u element=tree.xpath(“//kml:document”,名称空间=ns)[0]
文档元素。插入(1,样式元素)

显示
ns
变量的内容,以及如何到达
placemark
变量。(简而言之:做一个)@Tomalak,刚刚添加了ns。我不知道这样行不行。我对KML和编码都非常缺乏经验,ns变量是我从谷歌上学到的,可能不完整。请告诉我是否需要更多信息/改进,然后有人才能帮助回答。名称空间映射看起来不错,但从您的代码中仍然不清楚placemark包含什么内容。假设这实际上包含正确的元素,那么XPath也可以。但是,请尝试设置此选择的
元素的
schemaUrl
属性,而不是尝试设置
文本
。显示
ns
变量的内容,以及如何到达
placemark
变量。(简而言之:做一个)@Tomalak,刚刚添加了ns。我不知道这样行不行。我对KML和编码都非常缺乏经验,ns变量是我从谷歌上学到的,可能不完整。请告诉我是否需要更多信息/改进,然后有人才能帮助回答。名称空间映射看起来不错,但从您的代码中仍然不清楚placemark包含什么内容。假设这实际上包含了正确的元素,那么XPath就可以了
from lxml import etree

ns = {"kml": "http://www.opengis.net/kml/2.2"}

parser = etree.XMLParser(remove_blank_text=True, strip_cdata=False)
tree = etree.parse("your_kml_file.xml", parser)

schema_element = tree.xpath("//kml:Schema", namespaces=ns)[0]
schema_element.set("id", "test_1")

schemadata_element = tree.xpath("//kml:SchemaData", namespaces=ns)[0]
schemadata_element.set("schemaUrl", "#test_1")

# Remove existing "Style" element and add "styleUrl" element 
old_style_element = tree.xpath("//kml:Style", namespaces=ns)[0] 
placemark = old_style_element.getparent()
placemark.remove(old_style_element)

styleurl_element = etree.Element(etree.QName(ns["kml"], "styleUrl"))
styleurl_element.text = "#falseColor"
placemark.insert(0, styleurl_element)

# Add new "Style" element 
style_str = """
<Style id="falseColor" xmlns="http://www.opengis.net/kml/2.2">
    <BalloonStyle>
        <text><![CDATA[<table border="0">
            <tr><td><b>ID</b></td><td>$[test/id]</td></tr>
            <tr><td><b>LAT</b></td><td>$[test/LAT]</td></tr>
            <tr><td><b>LON</b></td><td>$[test/LONG]</td></tr>
            </table>]]> 
        </text>
    </BalloonStyle>
    <PolyStyle>
       <colorMode>random</colorMode>
    </PolyStyle>
</Style>"""

style_element = etree.fromstring(style_str, parser)

document_element = tree.xpath("//kml:Document", namespaces=ns)[0] 
document_element.insert(1, style_element)