Переопределить пространство имен с помощью 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:
...
Как мне изменить поведение префикса и что нужно вернуть, когда заканчивается функция?
Ответы
Ответ 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, подходящая для поиска. Пространство имен находится в пространстве имен.