[英]How to find elements by 'id' field in SVG file using Python
以下是.svg文件(xml)的摘录:
<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')
继续其他问题我已经尝试在svgTemplate
对象上使用setIdAttribute('id')
而没有运气。
结论:请提示一个聪明的方法来提取所有这些具有libcode-XX
形式的id
的text
元素。 之后,获取tspan
文本并将其替换为生成的内容应该没有问题。
对不起,我不知道我在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))
如果用'xml:id'替换'id',它会起作用吗?
如果minidom不知道svg,它可能会将'id'属性视为任何其他属性,而不是类型ID。 符合svg的实现会将svg内容中的'id'属性识别为ID类型,并且如果文件被正确标记,则加载外部DTD的xml实现也应该正确识别它。 在XML中加载外部DTD是可选的,因此修复此问题的正确方法是使解析器具有svg感知能力。
SVG 1.1 DTD中'id'的定义: http : //www.w3.org/TR/SVG11/svgdtd.html#DTD.1.4
在使用xpath时添加一点MattH的一个很好的例子,你知道命名空间,你可以做的事情
pub_name = data.xpath('//dc:publisher/cc:Agent/dc:title',
namespaces=nsmap)[0].text
这将直接访问您想要的元素标记文本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.