Подтвердить что ты не робот

Переопределить пространство имен с помощью ElementTree в Python

По умолчанию, когда вы вызываете ElementTree.parse(someXMLfile), библиотека Python ElementTree префикрует каждый разобранный node с его URI пространства имен в обозначении Кларка:

    {http://example.org/namespace/spec}mynode

Это делает доступ к определенным узлам по имени огромной болью позже в коде.

Я прочитал документы в ElementTree и пространствах имен, и похоже, что функция iterparse() должна позволить мне изменить способ, которым парсер префикс пространства имен, но для жизни меня я не могу заставить его изменить префикс. Похоже, что это может происходить в фоновом режиме до того, как событие ns-start даже срабатывает, как в этом примере:

for event, elem in iterparse(source):
    if event == "start-ns":
        namespaces.append(elem)
    elif event == "end-ns":
        namespaces.pop()
    else:
        ...

Как мне изменить поведение префикса и что нужно вернуть, когда заканчивается функция?

4b9b3361

Ответ 1

Вам не нужно использовать iterparse. Вместо этого, script:

from cStringIO import StringIO
import xml.etree.ElementTree as ET

NS_MAP = {
    'http://www.red-dove.com/ns/abc' : 'rdc',
    'http://www.adobe.com/2006/mxml' : 'mx',
    'http://www.red-dove.com/ns/def' : 'oth',
}

DATA = '''<?xml version="1.0" encoding="utf-8"?>
<rdc:container xmlns:mx="http://www.adobe.com/2006/mxml"
                 xmlns:rdc="http://www.red-dove.com/ns/abc"
                 xmlns:oth="http://www.red-dove.com/ns/def">
  <mx:Style>
    <oth:style1/>
  </mx:Style>
  <mx:Style>
    <oth:style2/>
  </mx:Style>
  <mx:Style>
    <oth:style3/>
  </mx:Style>
</rdc:container>'''

tree = ET.parse(StringIO(DATA))
some_node = tree.getroot().getchildren()[1]
print ET.fixtag(some_node.tag, NS_MAP)
some_node = some_node.getchildren()[0]
print ET.fixtag(some_node.tag, NS_MAP)

производит

('mx:Style', None)
('oth:style2', None)

Что показывает, как вы можете получить доступ к полностью определенным именам тегов для отдельных узлов в разборе дерева. Вы должны уметь адаптировать это к вашим конкретным потребностям.

Ответ 2

xml.etree.ElementTree, похоже, не имеет fixtag, ну, не в соответствии с документацией. Однако я посмотрел на некоторый исходный код для fixtag, и вы это делаете:

import xml.etree.ElementTree as ET

for event, elem in ET.iterparse(inFile, events=("start", "end")):
    namespace, looktag = string.split(elem.tag[1:], "}", 1)

У вас есть строка тега в looktag, подходящая для поиска. Пространство имен находится в пространстве имен.