Как преобразовать URI пространства имен в префикс с помощью lxml? - PullRequest
1 голос
/ 04 мая 2019

lxml хранит все полные имена с полным URI пространства имен, например,

from lxml import etree

root = etree.fromstring('''
<a:doc xmlns:a="http://somesite.org/markup" xmlns:b="http://anothersite.org/markup" a:attr="foo">
  <b:e b:attr="bar"/>
</a:doc>''')

for el in root.iter():
    print("Element", el.tag)
    for a in el.attrib:
        print("  Attribute", a)

Распечатает

Element {http://somesite.org/markup}doc
  Attribute {http://somesite.org/markup}attr
Element {http://anothersite.org/markup}e
  Attribute {http://anothersite.org/markup}attr

Но что, если мне понадобится больше читаемых человеком выходных данных с префиксами пространства имен вместо URI? Как

Element a:doc
  Attribute a:attr
Element b:e
  Attribute b:attr

Конечно, я могу написать функцию преобразования самостоятельно, например,

def uri2prefix(name, nsmap):
    qname = etree.QName(name)
    for pref, uri in nsmap.items():
        if qname.namespace == uri:
            return pref + ':' + qname.localname
    return name

for el in root.iter():
    print("Element", uri2prefix(el.tag, el.nsmap))
    for a in el.attrib:
        print("  Attribute", uri2prefix(a, el.nsmap))

Но где-то в lxml должна быть та же самая функциональность, потому что lxml.etree.tostring() использует ее. К сожалению, я не смог найти это в документации. Может быть, кто-то знает магическую функцию, выполняющую работу?

1 Ответ

0 голосов
/ 04 мая 2019

Я не вижу лучшего решения, чем использование функции uri2prefix .

Единственное улучшение может быть для элемента: экземпляр _Element имеет префикс атрибут.Итак, вы можете изменить свой цикл так:

for el in root.iter():
    name = el.prefix + ':' + etree.QName(el).localname if el.prefix else etree.QName(el).localname
    print("Element", name)
    for a in el.attrib:
        print("  Attribute", uri2prefix(a, el.nsmap))
...