Доступ к атрибуту XMLNS с помощью Python Elementree? - PullRequest
18 голосов
/ 23 декабря 2009

Как получить доступ к атрибутам NS с помощью ElementTree?

со следующим:

<data xmlns="http://www.foo.net/a" xmlns:a="http://www.foo.net/a" book="1" category="ABS" date="2009-12-22">

Когда я пытаюсь получить root.get ('xmlns'), я возвращаюсь Нет, Категория и Дата в порядке, Любая помощь приветствуется ..

Ответы [ 3 ]

15 голосов
/ 23 декабря 2009

Я думаю element.tag это то, что вы ищете. Обратите внимание, что в вашем примере отсутствует косая черта, поэтому он не сбалансирован и не будет анализироваться. Я добавил один в моем примере.

>>> from xml.etree import ElementTree as ET
>>> data = '''<data xmlns="http://www.foo.net/a"
...                 xmlns:a="http://www.foo.net/a"
...                 book="1" category="ABS" date="2009-12-22"/>'''
>>> element = ET.fromstring(data)
>>> element
<Element {http://www.foo.net/a}data at 1013b74d0>
>>> element.tag
'{http://www.foo.net/a}data'
>>> element.attrib
{'category': 'ABS', 'date': '2009-12-22', 'book': '1'}

Если вы просто хотите узнать URI xmlns, вы можете разделить его с помощью такой функции:

def tag_uri_and_name(elem):
    if elem.tag[0] == "{":
        uri, ignore, tag = elem.tag[1:].partition("}")
    else:
        uri = None
        tag = elem.tag
    return uri, tag

Для получения дополнительной информации о пространствах имен и квалифицированных именах в ElementTree см. примеров effbot .

8 голосов
/ 14 апреля 2012

Посмотрите на документацию / примеры пространств имен effbot; в частности, функция parse_map . В нем показано, как добавить атрибут * ns_map * к каждому элементу, который содержит префикс / сопоставление URI, которое применяется к этому конкретному элементу.

Однако, это добавляет атрибут ns_map ко всем элементам. Для своих нужд я обнаружил, что мне нужна глобальная карта всех пространств имен, используемых для упрощения поиска элементов и их отсутствия.

Вот что я придумал:

import elementtree.ElementTree as ET

def parse_and_get_ns(file):
    events = "start", "start-ns"
    root = None
    ns = {}
    for event, elem in ET.iterparse(file, events):
        if event == "start-ns":
            if elem[0] in ns and ns[elem[0]] != elem[1]:
                # NOTE: It is perfectly valid to have the same prefix refer
                #     to different URI namespaces in different parts of the
                #     document. This exception serves as a reminder that this
                #     solution is not robust.    Use at your own peril.
                raise KeyError("Duplicate prefix with different URI found.")
            ns[elem[0]] = "{%s}" % elem[1]
        elif event == "start":
            if root is None:
                root = elem
    return ET.ElementTree(root), ns

При этом вы можете анализировать xml-файл и получать dict с отображениями пространства имен. Итак, если у вас есть XML-файл, подобный следующему («my.xml»):

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"\
>
<feed>
  <item>
    <title>Foo</title>
    <dc:creator>Joe McGroin</dc:creator>
    <description>etc...</description>
  </item>
</feed>
</rss>

Вы сможете использовать пространства имен xml и получать информацию для таких элементов, как dc: creator :

>>> tree, ns = parse_and_get_ns("my.xml")
>>> ns
{u'content': '{http://purl.org/rss/1.0/modules/content/}',
u'dc': '{http://purl.org/dc/elements/1.1/}'}
>>> item = tree.find("/feed/item")
>>> item.findtext(ns['dc']+"creator")
'Joe McGroin'
0 голосов
/ 19 октября 2018

Попробуйте это:

import xml.etree.ElementTree as ET
import re
import sys

with open(sys.argv[1]) as f:
    root = ET.fromstring(f.read())
    xmlns = ''
    m = re.search('{.*}', root.tag)
    if m:
        xmlns = m.group(0)
    print(root.find(xmlns + 'the_tag_you_want').text)
...