2014-07-25 30 views
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> 
... 

回答

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 
+0

的解決方案是簡單得多比我預想的,但不知爲何,分配不這樣做首先在幕後。我假設有一些__magic__方法實現(可以覆蓋)賦值行爲。 pytype命名空間如何參與?我幾次閱讀lxml文檔,沒有真正理解客體化的東西。 – Mike

+1

@Mike,根據['lxml.objectify'文檔](http://lxml.de/objectify.html):'objectify.E'是objectify.ElementMaker的一個實例。默認情況下,它會創建沒有命名空間的pytype註釋元素。您可以通過將False傳遞給構造函數的annotate關鍵字參數來關閉pytype註釋。 – falsetru

+0

@Mike,所以,'M = objectify.ElementMaker(annotate = False); el.xpath('./ ..')[0] .styleUrl = M.xyz('#'+ to)'可以是另一種解決方案。 (似乎,mehtod名稱'xyz'並不重要,除非該調用包含另一個調用,例如:'M.xyz(M.xyz('123'))') – falsetru