Python: ElementTree, получить строку пространства имен элемента
Этот XML файл имеет имя example.xml
:
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>14.0.0</modelVersion>
<groupId>.com.foobar.flubber</groupId>
<artifactId>uberportalconf</artifactId>
<version>13-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Environment for UberPortalConf</name>
<description>This is the description</description>
<properties>
<birduberportal.version>11</birduberportal.version>
<promotiondevice.version>9</promotiondevice.version>
<foobarportal.version>6</foobarportal.version>
<eventuberdevice.version>2</eventuberdevice.version>
</properties>
<!-- A lot more here, but as it is irrelevant for the problem I have removed it -->
</project>
Если я загружу example.xml и проанализирую его с помощью ElementTree, я могу увидеть, что его пространство имен - http://maven.apache.org/POM/4.0.0
.
>>> from xml.etree import ElementTree
>>> tree = ElementTree.parse('example.xml')
>>> print tree.getroot()
<Element '{http://maven.apache.org/POM/4.0.0}project' at 0x26ee0f0>
Я не нашел метод вызова, чтобы получить просто пространство имен из Element
не прибегая к синтаксическому анализу str(an_element)
элемента. Похоже, что должен быть лучший способ.
Ответы
Ответ 1
Пространство имен должно находиться в Element.tag
прямо перед "фактическим" тегом:
>>> root = tree.getroot()
>>> root.tag
'{http://maven.apache.org/POM/4.0.0}project'
Чтобы узнать больше об пространствах имен, взгляните на ElementTree: работа с пространствами имен и квалифицированными именами.
Ответ 2
Это идеальная задача для регулярного выражения.
import re
def namespace(element):
m = re.match('\{.*\}', element.tag)
return m.group(0) if m else ''
Ответ 3
Я не уверен, возможно ли это с помощью xml.etree
, но вот как вы могли это сделать с помощью lxml.etree
:
>>> from lxml import etree
>>> tree = etree.parse('example.xml')
>>> tree.xpath('namespace-uri(.)')
'http://maven.apache.org/POM/4.0.0'
Ответ 4
Без использования регулярных выражений:
>>> root
<Element '{http://www.google.com/schemas/sitemap/0.84}urlset' at 0x2f7cc10>
>>> root.tag.split('}')[0].strip('{')
'http://www.google.com/schemas/sitemap/0.84'
Ответ 5
Я думаю, будет легче взглянуть на атрибуты:
>>> root.attrib
{'{http://www.w3.org/2001/XMLSchema-instance}schemaLocation':
'http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'}
Ответ 6
lxml.xtree
библиотеки lxml.xtree
имеет словарь под названием nsmap
, который показывает все пространство имен, которое используется в текущей области тега.
>>> item = tree.getroot().iter().next()
>>> item.nsmap
{'md': 'urn:oasis:names:tc:SAML:2.0:metadata'}
Ответ 7
Короткий ответ:
ElementTree._namspace_map[ElementTree._namspace_map.values().index('')]
но только если вы звонили
ElementTree.register_namespace(prefix,uri)
в ответ на каждое событие == "start-ns", полученное во время итерации через результат
ET.iterparse(...)
и вы зарегистрировались для "start-ns"
Ответ на вопрос "что такое пространство имен по умолчанию?", Необходимо уточнить два момента:
(1) Спецификации XML говорят, что пространство имен по умолчанию не обязательно является глобальным по всему дереву, а пространство имен по умолчанию может быть повторно объявлено в любом элементе под root и наследуется вниз, пока не будет повторено повторное объявление другого пространства имен по умолчанию.
(2) Модуль ElementTree может (де-факто) обрабатывать XML-подобные документы, которые не имеют корневого пространства имен по умолчанию, -если они не используют пространство имен в любом месте документа. (* могут быть менее строгие условия, например, "если" и не обязательно "iff").
Вероятно, также стоит подумать: "Чего вы хотите?" Учтите, что XML файлы могут быть семантически эквивалентными, но синтаксически очень разными. Например, следующие три файла семантически эквивалентны, но у A.xml есть одно объявление пространства имен по умолчанию, B.xml имеет три, а C.xml - нет.
A.xml:
<a xlmns="http://A" xlmns:nsB0="http://B0" xlmns:nsB1="http://B1">
<nsB0:b/>
<nsB1:b/>
</a>
B.xml:
<a xlmns="http://A">
<b xlmns="http://B0"/>
<b xlmns="http://B1"/>
</a>
C.xml:
<{http://A}a>
<{http://B0}b/>
<{http://B1}b/>
</a>
Файл C.xml - это каноническое расширенное синтаксическое представление, представленное в функции поиска ElementTree.
Если вы уверены, что не будет конфликтов имен пространства, вы можете изменить теги элементов при разборе, как описано здесь: Модуль Python ElementTree: как игнорировать пространство имен XML файлов, чтобы найти соответствующий элемент при использовании метода "найти", "найти все"
Ответ 8
Объединив некоторые из приведенных выше ответов, я думаю, что самый короткий код
theroot = tree.getroot()
theroot.attrib[theroot.keys()[0]]