Python: ElementTree, получить строку пространства имен элемента - PullRequest
17 голосов
/ 01 марта 2012

Этот 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) Элемента. Кажется, должен быть лучший путь.

Ответы [ 8 ]

21 голосов
/ 01 марта 2012

Пространство имен должно быть в Element.tag прямо перед тегом «фактический»:

>>> root = tree.getroot()
>>> root.tag
'{http://maven.apache.org/POM/4.0.0}project'

Чтобы узнать больше о пространствах имен, взгляните на ElementTree: Workingс пространствами имен и квалифицированными именами .

14 голосов
/ 18 октября 2012

Это идеальное задание для регулярного выражения .

import re

def namespace(element):
    m = re.match('\{.*\}', element.tag)
    return m.group(0) if m else ''
11 голосов
/ 01 марта 2012

Я не уверен, возможно ли это с 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'
7 голосов
/ 02 февраля 2015

Без использования регулярных выражений:

>>> 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'
1 голос
/ 02 ноября 2017

объединяя некоторые из ответов выше, я думаю, что самый короткий код -

theroot = tree.getroot()
theroot.attrib[theroot.keys()[0]]
1 голос
/ 01 марта 2012

Я думаю, что будет проще взглянуть на атрибуты:

>>> 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'}
0 голосов
/ 21 апреля 2017

Короткий ответ:

ElementTree._namspace_map[ElementTree._namspace_map.values().index('')]

, но только если вы звоните

ElementTree.register_namespace(prefix,uri)

в ответ на каждое событие == "start-ns" получен во время итерации по результату

ET.iterparse(...) 

, и вы зарегистрировались для "start-ns"

Ответ на вопрос "что такое пространство имен по умолчанию?", необходимо уточнить два момента:

(1) Спецификации XML говорят, что пространство имен по умолчанию не обязательно является глобальным по всему дереву, а пространство имен по умолчанию может быть повторно объявлено в любом элементе в корневом каталоге и наследуетсявниз до встречи с другим повторным объявлением пространства имен по умолчанию.

(2) Модуль ElementTree может (де-факто) обрабатывать XML-подобные документы, которые не имеют корневого пространства имен по умолчанию, - если они не используются пространством имен где-либо вдокумент.(* могут быть менее строгие условия, например, «если» и необязательно «если»).

Вероятно, стоит подумать, "для чего ты этого хочешь?"Учтите, что файлы 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 для поиска соответствующего элемента при использовании методов «find», «findall»

0 голосов
/ 30 августа 2016

Элемент библиотеки lxml.xtree имеет словарь под названием nsmap, который показывает все пространство имен, используемое в текущей области тегов.

>>> item = tree.getroot().iter().next()
>>> item.nsmap
{'md': 'urn:oasis:names:tc:SAML:2.0:metadata'}
...