Python:ElementTree,获取Element的命名空间字符串

时间:2012-03-01 09:22:00

标签: 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)。似乎必须有更好的方法。

9 个答案:

答案 0 :(得分:21)

命名空间应位于Element.tag的“实际”标记之前:

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

要了解有关命名空间的更多信息,请查看ElementTree: Working with Namespaces and Qualified Names

答案 1 :(得分:14)

这是regular expression的完美任务。

import re

def namespace(element):
    m = re.match('\{.*\}', element.tag)
    return m.group(0) if m else ''

答案 2 :(得分:11)

我不确定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'

答案 3 :(得分:7)

不使用正则表达式:

>>> 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'

答案 4 :(得分:1)

我认为查看属性会更容易:

>>> 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'}

答案 5 :(得分:1)

结合上面的一些答案,我认为最短的代码是

theroot = tree.getroot()
theroot.attrib[theroot.keys()[0]]

答案 6 :(得分:0)

lxml.xtree库的元素有一个名为nsmap的字典,它显示了当前标记范围中使用的所有命名空间。

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

答案 7 :(得分:0)

简短的回答是:

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

但只有在你打电话的时候

ElementTree.register_namespace(prefix,uri)

响应每个事件==&#34; start-ns&#34; 在迭代结果时收到

ET.iterparse(...) 

您注册了&#34; start-ns&#34;

答案问题&#34;什么是默认命名空间?&#34;,有必要澄清两点:

(1)XML规范说默认命名空间在整个树中不一定是全局的,而是可以在root下的任何元素上重新声明默认命名空间,并向下继承,直到遇到另一个默认命名空间重新声明。

(2)ElementTree模块可以(事实上)处理没有根默认名称空间的类似XML的文档,如果它们在文档中的任何地方都没有使用名称空间。 (*可能有不太严格的条件,例如,&#34;如果&#34;并且不一定&#34; iff&#34;)。

它可能也值得考虑&#34;你想要它做什么?&#34;考虑到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 module: How to ignore the namespace of XML files to locate matching element when using the method "find", "findall"

答案 8 :(得分:0)

这是我在 ElementTree 3.9+ 上的解决方案,


System.InvalidOperationException: Value Dispose() cannot be called while doing CreateHandle().
   at System.Windows.Forms.Control.Dispose(Boolean disposing)
   at System.ComponentModel.Component.Dispose()
   at System.Windows.Forms.Control.Dispose(Boolean disposing)
   at System.ComponentModel.Component.Dispose()
   at System.Windows.Forms.Control.Dispose(Boolean disposing)
   at TabContent.TabContentControl.Dispose(Boolean disposing) in c:\Users\User\Desktop\Trading Panel\Trading Panel\TabContent\TabContentControl.Designer.cs:line 20
   at System.ComponentModel.Component.Dispose()
   at System.Windows.Forms.Control.Dispose(Boolean disposing)
   at System.ComponentModel.Component.Dispose()
   at cAlgo.Panel.HandlePositionClosed(PositionClosedEventArgs args) in c:\Users\User\Desktop\Trading Panel\Sources\Robots\PanelOriginal\PanelOriginal\Panel.cs:line 349

这将返回一个 [prefix:URL] 元组数组,如下所示:


  private void HandlePositionClosed(PositionClosedEventArgs args)
         {
            if (_robot.PositionsByLabel.All(x => x.SymbolName != args.Position.SymbolName))
            {
                var customTab = _customTabs
                    .ToList()
                    .FirstOrDefault(x => x.Text.Contains(args.Position.SymbolName));

                if (customTab != null)
                {
                    
                    tabControl1.Controls.Remove(customTab);
                    customTab.Dispose();
                    _customTabs.Remove(customTab);
                    
                }
            }
        }


protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }