2012-03-01 20 views
12

這個XML文件被命名爲example.xml的:的Python:ElementTree中,獲得命名空間的字符串的元素

<?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)。似乎有一個更好的方法。

+0

你知道如何在這種情況下使用find方法嗎?它沒有在這裏工作... – caarlos0 2012-05-05 03:48:26

回答

10

我不知道這是可能的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' 
+1

我在Windows中使用Python 2.7.2獲得'unresolved import:etree'。 'xpath'在使用'xml.etree'時沒有可用的方法,如果我使用'find()'(它支持xpath表達式)''namespace-uri(。)''語句仍然不起作用。 – Deleted 2012-03-02 14:55:14

+0

這正是我正在尋找的,[見公關](https://github.com/samatjain/gpxsplitter/pull/3) – 2015-09-21 09:43:24

+0

這是我見過的最好的解決方案。我通常使用xmlstarlet,但我現在可以切換。 – 2016-04-22 20:42:00

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

肯定比解析'str(the_element)'容易。但我想解析'the_element.tag'甚至更容易一些。因爲我只對命名空間感興趣。你怎麼看? – Deleted 2012-03-02 15:13:07

+1

我認爲@ RikPoggi的答案似乎是最好的答案(實際上,我贊成它)。實際上,獲取名稱空間應該像're.search('\ {(。*)\}',the_element.tag).group(1)'一樣簡單。用我的答案,看起來你可以使用'the_element.attrib.values()[0] .split()[0]',但實際上,它看起來並不那麼直截了當,並不能保證你贏得'未來還有其他屬性。 – jcollado 2012-03-02 15:21:41

12

這是regular expression的完美任務。

import re 

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

經過一段時間的爭論後,這是我找到的最佳解決方案。我不能相信這個API不會讓你有辦法去請求這個命名空間,並且在做'rootElement.keys()'的時候它不會返回屬性'xmlns'。當然有一個很好的理由,但我現在找不到它。 – Robert 2015-07-09 18:03:19

5

不使用正則表達式:

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

類似的回答'root.tag [1:root.tag.index('}')]' – watashiSHUN 2016-12-14 08:35:06

0

lxml.xtree庫的元素有一個叫做nsmap字典,它顯示了所有在當前標籤範圍使用的命名空間。

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

簡短的回答是:

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

但只有當你一直在呼籲

ElementTree.register_namespace(prefix,uri) 

響應每事件== 「啓動NS」收到,而迭代通過

ET.iterparse(...) 

和您註冊「啓動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 module: How to ignore the namespace of XML files to locate matching element when using the method "find", "findall"

0

結合上面一些問題的答案,我想在最短的代碼是

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