1
我不知道如何替換已經有一個命名空間(pytype除外)的lxml StringElement(在這種情況下是styleUrl)的內容。我最終得到了一個注入的元素級名稱空間。這是一個非常蒸餾水和簡化版本,只是試圖重新命名一個StyleMap設定來說明這個問題:用開始命名空間戰爭替換lxml StringElement的內容?
#!/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>
...
的解決方案是簡單得多比我預想的,但不知爲何,分配不這樣做首先在幕後。我假設有一些__magic__方法實現(可以覆蓋)賦值行爲。 pytype命名空間如何參與?我幾次閱讀lxml文檔,沒有真正理解客體化的東西。 – Mike
@Mike,根據['lxml.objectify'文檔](http://lxml.de/objectify.html):'objectify.E'是objectify.ElementMaker的一個實例。默認情況下,它會創建沒有命名空間的pytype註釋元素。您可以通過將False傳遞給構造函數的annotate關鍵字參數來關閉pytype註釋。 – falsetru
@Mike,所以,'M = objectify.ElementMaker(annotate = False); el.xpath('./ ..')[0] .styleUrl = M.xyz('#'+ to)'可以是另一種解決方案。 (似乎,mehtod名稱'xyz'並不重要,除非該調用包含另一個調用,例如:'M.xyz(M.xyz('123'))') – falsetru