【问题标题】:Using namespaces in lxml在 lxml 中使用命名空间
【发布时间】:2018-05-11 21:10:07
【问题描述】:

我正在尝试使用 lxml 进行 svg 解析并与命名空间作斗争。

问题:

  1. 如何使用tree.iterfind 和命名空间映射遍历所有image 标签? tree.iterfind('image', root.nsmap) 不返回任何东西,更丑的 tree.iter('{http://www.w3.org/2000/svg}image') 有效
  2. 我正在尝试将image 标签转换为use 标签。虽然 lxml 给了我一个带有 xlinx:href 的属性字典,但它在将它传递给 makeelement 时会窒息,有没有优雅的解决方案?
  3. 我应该使用lxml 还是有更好的方法(更直接)?我的目标是将image 标签重写为use 标签并将引用的svgs 的内容嵌入符号中。 (到目前为止,lxml 和我遇到的命名空间问题似乎令人反感)。

.

from lxml import etree

def inlineSvg(path):
    parser = etree.XMLParser(recover=True)
    tree = etree.parse(path, parser)

    root = tree.getroot()
    print(root.nsmap)


    for img in tree.iter('{http://www.w3.org/2000/svg}image'):
    #for img in tree.iterfind('image', root.nsmap): #for some reason I can't get this to work...
        print(img)

        #we have to translate xlink: to {http://www.w3.org/1999/xlink} for it to work, despit the lib returning xlink: ...
        settableAttributes = dict(img.items()) #img.attribute
        settableAttributes['{http://www.w3.org/1999/xlink}href'] = settableAttributes['xlink:href']
        del settableAttributes['xlink:href']

        print(etree.tostring(img.makeelement('use', settableAttributes)))

【问题讨论】:

    标签: python python-3.x lxml


    【解决方案1】:
    • 如何使用 tree.iterfind 和 namsepace 映射遍历所有图像标签?
    for img in root.iterfind('image', namespaces=root.nsmap):
    
    • 我正在尝试将图像标签转换为使用标签。虽然 lxml 给了我一个带有 xlinx:href 的属性字典,但它在将它传递给 makeelement 时感到窒息,是否有一个优雅的解决方案?

    这些都适合我:

    img.makeelement('use', dict(img.items())
    img.makeelement('use', img.attrib)
    
    • 我应该使用 lxml 还是有更好的方法(更直接)?

    每个人都有意见。我喜欢lxml。我觉得它非常简单。您的意见可能不同。


    完整的程序:

    from lxml import etree
    
    def inlineSvg(path):
        parser = etree.XMLParser(recover=True)
        tree = etree.parse(path, parser)
    
        root = tree.getroot()
    
        for img in root.iterfind('image', namespaces=root.nsmap):
            use = img.makeelement('use', img.attrib, nsmap=root.nsmap)
            print(etree.tostring(use))
    
    inlineSvg('xx.svg')
    

    输入文件(xx.svg):

    <svg xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink">
    
      <rect x="10" y="10" height="130" width="500" style="fill: #000000"/>
    
      <image x="20" y="20" width="300" height="80"
         xlink:href="http://jenkov.com/images/layout/top-bar-logo.png" />
    
      <line x1="25" y1="80" x2="350" y2="80"
                style="stroke: #ffffff; stroke-width: 3;"/>
    </svg>
    

    结果:

    $ python xx.py 
    b'<use xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" height="80" width="300" x="20" y="20" xlink:href="http://jenkov.com/images/layout/top-bar-logo.png"/>'
    

    参考:

    【讨论】:

    • 很好的一般答案。我认为img.makeelement('use', img.attrib) 对我不起作用的问题是我的svg 文件错过了xmlns:xlink="http://www.w3.org/1999/xlink"。有什么办法可以添加吗?
    • 也许吧。请编辑您的问题以包含一个简短、完整的 SVG 文件来演示错误。
    • 目前我已经使用etree.register_namespace('xlink','http://www.w3.org/1999/xlink') 解决了我的问题。由于我的一些问题可能与 centos 上的 pipyum 有关(动态库可能有错误的版本),我认为深入研究这一点没有多大意义。但是,如果您仍然感兴趣,请查看 questionanswer。它包含一个最小的示例 svg,并且是研究 etree 的原因,答案就是结果
    • 由于脚本完成了这项工作,我只希望找到一种更好的方法来找到插入命名空间的更好方法(因为我的解决方案是丑陋的硬编码)。
    猜你喜欢
    • 1970-01-01
    • 2012-09-12
    • 2011-12-24
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多