2010-03-01 52 views
3

下面是從.svg文件的摘錄(這是XML)找到SVG文件由「ID」字段元素:如何使用Python

<text 
     xml:space="preserve" 
     style="font-size:14.19380379px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono;-inkscape-font-specification:DejaVu Sans Mono" 
     x="109.38555" 
     y="407.02847" 
     id="libcode-00" 
     sodipodi:linespacing="125%" 
     inkscape:label="#text4638"><tspan 
     sodipodi:role="line" 
     id="tspan4640" 
     x="109.38555" 
     y="407.02847">12345678</tspan></text> 

我正在學習Python和不知道如何能我發現所有這樣的text元素的id字段等於libcode-XX,其中XX是一個數字。

我已經使用minidom的解析器加載了這個.svg文件,並嘗試使用getElementById來查找元素。但是我得到None的結果。

svgTemplate = minidom.parse(svgFile) 
    print svgTemplate 
    print svgTemplate.getElementById('libcode-00') 

後其他SO問題,我在沒有運氣svgTemplate對象使用setIdAttribute('id')試圖去。底線:請提供一個巧妙的方式來提取所有這些text元素的id元素,其形式爲libcode-XX。之後,獲取tspan文本並將其替換爲生成的內容應該沒有問題。

回答

10

對不起,我不知道我的方式圍繞minidom。另外,我必須從示例svg文檔中找到命名空間聲明,以便您的摘錄可以加載。

我個人使用lxml.etree。我建議您使用XPATH來處理XML文檔的部分內容。它非常強大,如果你在掙扎,這裏有幫助。

關於XPATH和etree,SO上有很多答案。我寫了幾個。

from lxml import etree 
data = """ 
<svg 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:cc="http://web.resource.org/cc/" 
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    xmlns:svg="http://www.w3.org/2000/svg" 
    xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 
    width="50" 
    height="25" 
    id="svg2" 
    sodipodi:version="0.32" 
    inkscape:version="0.45.1" 
    version="1.0" 
    sodipodi:docbase="/home/tcooksey/Projects/qt-4.4/demos/embedded/embeddedsvgviewer/files" 
    sodipodi:docname="v-slider-handle.svg" 
    inkscape:output_extension="org.inkscape.output.svg.inkscape"> 
    <text 
     xml:space="preserve" 
     style="font-size:14.19380379px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono;-inkscape-font-specification:DejaVu Sans Mono" 
     x="109.38555" 
     y="407.02847" 
     id="libcode-00" 
     sodipodi:linespacing="125%" 
     inkscape:label="#text4638"><tspan 
     sodipodi:role="line" 
     id="tspan4640" 
     x="109.38555" 
     y="407.02847">12345678</tspan></text> 
    </svg> 
""" 

nsmap = { 
    'sodipodi': 'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd', 
    'cc': 'http://web.resource.org/cc/', 
    'svg': 'http://www.w3.org/2000/svg', 
    'dc': 'http://purl.org/dc/elements/1.1/', 
    'xlink': 'http://www.w3.org/1999/xlink', 
    'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 
    'inkscape': 'http://www.inkscape.org/namespaces/inkscape' 
    } 


data = etree.XML(data) 

# All svg text elements 
>>> data.xpath('//svg:text',namespaces=nsmap) 
[<Element {http://www.w3.org/2000/svg}text at b7cfc9dc>] 
# All svg text elements with id="libcode-00" 
>>> data.xpath('//svg:text[@id="libcode-00"]',namespaces=nsmap) 
[<Element {http://www.w3.org/2000/svg}text at b7cfc9dc>] 
# TSPAN child elements of text elements with id="libcode-00" 
>>> data.xpath('//svg:text[@id="libcode-00"]/svg:tspan',namespaces=nsmap) 
[<Element {http://www.w3.org/2000/svg}tspan at b7cfc964>] 
# All text elements with id starting with "libcode" 
>>> data.xpath('//svg:text[fn:startswith(@id,"libcode")]',namespaces=nsmap) 
[<Element {http://www.w3.org/2000/svg}text at b7cfcc34>] 
# Iterate text elements, access tspan child 
>>> for elem in data.xpath('//svg:text[fn:startswith(@id,"libcode")]',namespaces=nsmap): 
...  tp = elem.xpath('./svg:tspan',namespaces=nsmap)[0] 
...  tp.text = "new text" 

open("newfile.svg","w").write(etree.tostring(data)) 
+1

如何用tspan元素替換文本(tp =「newtext」),然後使用此方法將修改的XML導出到新的SVG文件? Minidom有toxml()。 – 2010-03-02 07:28:37

+0

您可以直接修改etree元素。您可以使用'etree.tostring(xmldata)'導出爲新文件,如上面更新示例所示。 – MattH 2010-03-02 08:07:01

+0

是否需要準備nsmap?我看到它被用在所有的表達式中。 – 2010-03-02 09:16:35

0

如果您用'xml:id'替換'id',它會起作用嗎?

如果minidom不知道svg,它可能會將'id'屬性視爲任何其他屬性,而不是類型ID。一致的svg實現可以將svg內容中的'id'屬性識別爲ID類型,並且加載外部DTD的xml實現也應該在文件被正確標記時正確識別它。在XML中加載外部DTD是可選的,因此解決此問題的正確方法是使分析器瞭解svg。在SVG 1.1 DTD「身份證」的

定義:http://www.w3.org/TR/SVG11/svgdtd.html#DTD.1.4

0

添加一點點MattH的很好的例子,當你使用XPath,你知道的命名空間,你可以做這樣的事情

pub_name = data.xpath('//dc:publisher/cc:Agent/dc:title', 
          namespaces=nsmap)[0].text 

這將直接訪問你想要的元素標籤文本。