用起始命名空间战争替换lxml StringElement的内容?

时间:2014-07-25 12:41:57

标签: python lxml kml

我无法弄清楚如何替换已经具有命名空间(除pytype之外)的lxml StringElement(在本例中为styleUrl)的内容。我最终注入了元素级命名空间。这是一个非常精简和简化的版本,只试图重命名一个StyleMap来说明问题:

#!/usr/bin/env python

from __future__ import print_function
import sys
from pykml import parser as kmlparser
from lxml import objectify

frm = "lineStyle30218901714341461519022"
to = "s1"

b4_et = kmlparser.parse('b4.kml')
b4_root = b4_et

el = b4_root.xpath('//*[@id="%s"]' % frm)[0]
el.attrib['id'] = to

el = b4_root.xpath('//*[text()="#%s"]' % frm)[0]
el.xpath('./..')[0].styleUrl = '#'+to

objectify.deannotate(b4_root, xsi_nil=True)
b4_et.write(sys.stdout, pretty_print=True)

测试数据:

<?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>Wasatch Trails</name>
    <open>1</open>
    <Style id="lineStyle30218901714341461519049">
        <LineStyle><color>ff0080ff</color><width>4</width></LineStyle>
    </Style>
    <Style id="lineStyle30218901714341461519027">
        <LineStyle><color>ff0080ff</color><width>4</width></LineStyle>
    </Style>
    <StyleMap id="lineStyle30218901714341461519022">
        <Pair><key>normal</key><styleUrl>#lineStyle30218901714341461519049</styleUrl></Pair>
        <Pair><key>highlight</key><styleUrl>#lineStyle30218901714341461519027</styleUrl></Pair>
    </StyleMap>
    <Placemark>
        <name>Trail</name>
        <styleUrl>#lineStyle30218901714341461519022</styleUrl>
        <LineString>
            <tessellate>1</tessellate>
            <coordinates>
                -111.6472637672589,40.4810633294269,0 -111.650415221546,40.48116138407261,0 -111.6504410181637,40.48118694372887,0
            </coordinates>
        </LineString>
    </Placemark>
</Document>
</kml>

我唯一无法解决的问题是lxml将 xmlns:py="http://codespeak.net/lxml/objectify/pytype" 属性放入新创建的styleUrl元素中。我猜这是由于文件具有kml / 2.2的默认命名空间。我不知道怎么告诉它新的styleUrl应该是kml而不是pytype。

...
<styleUrl xmlns:py="http://codespeak.net/lxml/objectify/pytype">#s1</styleUrl>
...

1 个答案:

答案 0 :(得分:1)

替换以下内容:

el.xpath('./..')[0].styleUrl = '#'+to

使用:

el.xpath('./..')[0].styleUrl = objectify.StringElement('#' + to)

会给你你想要的东西。但我不确定这是否是最佳方式。

顺便说一句,您可以使用set(key, value)方法设置属性值:

el.set('id', to)  # isntead of  el.attrib['id'] = to