lxml hiding 'xmlns' attribute of root
(在我问我的问题之前,请先讲一下下面的小故事!)
我有MathJax生成的一些SVG元素,生成后看起来像这样(在元素检查器中找到):
1 2 3 4 | <svg xmlns:xlink="http://www.w3.org/1999/xlink" width="6.768ex" height="2.468ex" viewBox="0 -825.2 2914.1 1062.4"> <defs>...</defs> <g>...</g> </svg> |
当我尝试以chrome或safari形式单独显示此SVG时,浏览器将显示以下错误消息:
This XML file does not appear to have any style information associated with it. The document tree is shown below. [...]
经过一些实验,我发现罪魁祸首是缺少的" xmlns"标签。 (我猜MathJax在具有此标签的页面中将另一个SVG放在更高的位置,因此在网页内部,无需再次重复它。等等。)即,将开始
1 2 3 4 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="6.768ex" height="2.468ex" viewBox="0 -825.2 2914.1 1062.4"> <defs>...</defs> <g>...</g> </svg> |
(请注意新的
好。好。
现在,我想自动执行添加丢失的
不幸的是(最后是我的问题!),lxml似乎隐藏了所有以'xmlns'开头的属性,我不知道为什么。虽然它允许我添加'xmlns'属性(例如,通过执行
其中
因此:(i)为什么lxml对我隐藏某些属性,并且(ii)不管为什么我只能在
我已经混合了两个关于名称空间的答案。 一个来自lxml:将名称空间添加到输入文件,另一个来自通过在python中使用lxml添加xml前缀声明。 第一个答案不涉及复制属性,因此我从第二个答案中借用了它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from lxml import etree from io import StringIO, BytesIO # excerpt from https://commons.wikimedia.org/wiki/File:SVG_logo.svg # note that xmlns is omitted xml = '<svg xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-50 -50 100 100"><rect id="background" x="-50" y="-50" width="100" height="100" rx="4" fill="#f90"/> <g id="c"> <circle id="n" cy="-31.6" r="7.1" fill="#fff"/> </g></svg>' tree = etree.parse(StringIO(xml)) root = tree.getroot() nsmap = root.nsmap nsmap[None] = 'http://www.w3.org/2000/svg' root2 = etree.Element(root.tag, nsmap=nsmap) root2[:] = root[:] for a in root.attrib: root2.attrib[a] = root.attrib[a] tree2 = etree.parse(StringIO(etree.tostring(root2, encoding="unicode"))) root3 = tree2.getroot() print(root3) # <Element {http://www.w3.org/2000/svg}svg at 0x58778f0> print(root3.nsmap) # {'xlink': 'http://www.w3.org/1999/xlink', None: 'http://www.w3.org/2000/svg'} |
这将为您工作,但我相信MathJax可以处理这种任务。