python - python svg 使用 minidom/etree/lxml 解析
问题描述
使用 python 我尝试使用 minidom/etree/lxml 解析 svg(xml 格式),我有以下 svg 文件:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:shaper="http://www.shapertools.com/namespaces/shaper"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="5319.4434mm"
height="6025.5mm"
viewBox="0 0 5319.4434 6025.5"
version="1.1"
id="svg1217"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="test.svg">
<defs
id="defs1211" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.0875"
inkscape:cx="2965.7333"
inkscape:cy="12836.281"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata1214">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Second_Layer"
style="display:inline">
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;opacity:1"
id="rect2567"
width="1233.7142"
height="1644.9524"
x="459.61902"
y="268.1666" />
</g>
<g
inkscape:label="First_Layer"
inkscape:groupmode="layer"
id="layer1"
transform="translate(2594.7098,2684.756)"
style="display:none">
<g
transform="matrix(10,0,0,10,-2594.7098,-2684.756)"
id="Body_Körper116">
<path
style="vector-effect:non-scaling-stroke;fill:#000000"
inkscape:connector-curvature="0"
d="M 241.25,-479.9 V -500 h 17.5 v 20.1 z"
shaper:cutDepth="0.0001105"
shaper:pathType="exterior"
transform="matrix(1,0,0,-1,-42.65,18.6)"
id="path2" />
</g>
<g
transform="matrix(10,0,0,10,-2594.7098,-2684.756)"
id="Body_Körper114">
<path
style="vector-effect:non-scaling-stroke;fill:#000000"
inkscape:connector-curvature="0"
d="M 141.95,-480.1 V -500 h 16.1 v 19.9 z"
shaper:cutDepth="0.0001103"
shaper:pathType="exterior"
transform="matrix(1,0,0,-1,-42.65,18.6)"
id="path5" />
</g>
其中包括 2 层(第 1 层和第 2 层),每层中有一些主体并分组。我想要做的是对这些物体执行操作(例如变换)以移动它们等。
我尝试了 minidom 和 etree,但在我的情况下,我无法清楚地了解这些树是如何构建和访问的。因此我有几个问题,希望有更多经验的人可以帮助我快速上轨道:)
使用时:
lxml = ET.parse('test.svg') svgdoc = lxml.getroot()
或者
svgdoc = xml.dom.minidom.parse('test.svg')
我设法将文件读入树中。有人能告诉我如何在上面的例子中访问每棵树、子树、属性等吗?期待像“svgdoc.parent[1].child[1].属性通过树及其节点,但我得到了很多错误。
例如,我将如何访问带有“id="Body_Körper114" 的 Body 的 "transform="matrix(10,0,0,10,-2594.7098,-2684.756)" 以及如何访问 "shaper:cutDepth="0.0001105"嵌套在 Body_Körper114 中?
我可以阅读它们,
path_d_strings = [path.getAttribute('d') for path in svgdoc.getElementsByTagName('path')]
但如果我想根据其中找到的某些条件更改不嵌套在路径内(但直接在上面)的变换,那么如果我使用 getElementsByTagName-Method,我最终会得到更多“变换”元素,如“ shaper:cutDepth" as "transform" 不仅出现在 path 作为 "shaper:cut..." 中,而且出现在上面的 body 描述中,因此我不能简单地按索引浏览列表并应用更改。我还觉得奇怪的是,我将 svgdoc 中的元素读取到其他一些列表中,在此列表中进行更改,然后在写入更改的同时写入 xml 文件。
path = svgdoc.getElementsByTagName("path")
firstchild = path[0]
firstchild.attributes["d"].value = "test"
f = open('test2.svg', 'w')
f.write(doc.toxml())
doc.unlink()
我本来希望在保存之前必须将我通过 getElements 提取的列表传输回 svgdoc。这种结构是如何工作的?
- 使用 Inkscape,我可以删除所有变换部分并将所有内容置于绝对坐标。当我需要转换身体并用我的脚本移动它们时,我需要插入一个新的“节点”?!?在路径下(如“style”或“inkscape”)并将其保存到 xml 文件中。我将如何管理这个?
很抱歉这篇长文,但这真的让我很烦恼,我试图了解发生了什么。我阅读了教程、文档、示例,但没有真正解释如何控制这个结构。此外,我是 python 新手,仍然需要了解语法(不幸的是没有太多时间,因为我有 2 个小孩)
感谢您的帮助,非常感谢!干杯,
托比
解决方案
你的帖子太长了,我看不懂。这是一个给你的例子。不知道能不能满足你的需求。如果您有任何问题,请留言。
from simplified_scrapy import SimplifiedDoc,req,utils
html = utils.getFileContent('test.svg')
doc = SimplifiedDoc(html)
path = doc.getElement('path') # Select element
path.setAttr('d','test') # Edit attribute
while True:
path = doc.getElement('path',start=path._end)
if not path: break
path.setAttr('d','test2')
utils.saveFile('test2.svg', doc.html)
推荐阅读
- mysql - 应该如何在 mysql 的查询中定义可选约束
- sql - 比较 SQL Server 中 2 个不同表的父子组合
- java - 我怎么做才能使您无法选择 JTabbedPane 顶部的选项卡?
- javascript - 有没有办法在页面加载时覆盖浏览器的默认滚动到哈希行为?
- javascript - 删除或忽略数组中的空单元格
- .net - Facebook 分享按钮间歇性工作
- javascript - 使用 javascript 进行页面转换的步骤进度条
- bpmn - 如何设计以不同方式使用活动的流程?
- html - HTML 卡片 CSS 过渡
- docker - Hyperledger Fabric 无法下载 Docker 镜像