【问题标题】:How to get element from svg using xpath python lxml, but returning empty list?如何使用xpath python lxml从svg获取元素,但返回空列表?
【发布时间】:2019-07-08 04:43:48
【问题描述】:

我正在尝试使用 python-3 和 lxml 编辑 SVG 文件。 到目前为止,我一直坚持使用 xpath 从 SVG 中获取元素。

from lxml import etree

boarder = etree.parse('boarder.svg')

Bd = boarder.xpath('//g/path')

print(Bd)

当我运行代码时,我会返回:

[]

这是一个空列表。 我正在尝试将g/path 元素作为元素访问,以便我可以更改其属性。

这是我正在使用的 SVG ('boarder.svg')

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   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"
   id="svg8"
   version="1.1"
   viewBox="0 0 10 10"
   height="10mm"
   width="10mm">
  <defs
     id="defs2" />
  <metadata
     id="metadata5">
    <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
     transform="translate(0,-287)"
     id="layer1">
    <path
       id="rect1379"
       d="m 1.1663527,287.97964 h 7.6672946 v 7.6673 H 1.1663527 Z"
       style="opacity:0.95;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
  </g>
</svg>

到目前为止,我已经尝试过:

【问题讨论】:

  • 请向我们展示您实际尝试过的内容。如果您考虑命名空间,它确实有效:Bd = boarder.xpath('//svg:g/svg:path', namespaces={"svg": "http://www.w3.org/2000/svg"}).
  • 你能提供一个元素前后的例子吗?
  • @mzjn 我对 xml 还是很满意。我不知道我必须添加 svg: 并定义名称空间。我认为只需设置namespaces 就足够了。如果我使用namespaces={ * : "http://www.w3.org/2000/svg"},我可以省略svg:吗?

标签: python-3.x svg xpath lxml


【解决方案1】:

要查找svg 元素,请尝试遵循xpath。使用local-name()name()

from lxml import etree,html

boarder = etree.parse('boarder.svg')
Bd = boarder.xpath('//*[local-name()="svg"]//*[local-name()="g"]/*[local-name()="path"]/@id')[0]
print(Bd)
Bd = boarder.xpath('//*[local-name()="svg"]//*[local-name()="g"]/*[local-name()="path"]/@d')[0]
print(Bd)

Bd = boarder.xpath('//*[name()="svg"]//*[name()="g"]/*[name()="path"]/@id')[0]
print(Bd)
Bd = boarder.xpath('//*[name()="svg"]//*[name()="g"]/*[name()="path"]/@d')[0]
print(Bd)

输出:

rect1379
m 1.1663527,287.97964 h 7.6672946 v 7.6673 H 1.1663527 Z

【讨论】:

  • 编写这样的路径表达式是不必要的复杂。正确的方法是定义一个带有前缀的命名空间,然后为元素名称添加前缀。
  • @MathiasMüller 我该怎么做?你能提供任何代码示例吗?
【解决方案2】:

类似于 mzjn 对 OP 的评论,我想出了一种更通用/更好地做到这一点的方法:

boarder = etree.parse('boarder.svg')
ns = boarder.getroot().nsmap
Bd = boarder.xpath('//g/path', ns)
print(Bd)

这也适用于 find、findall 和 iterfind。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-08
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    相关资源
    最近更新 更多