2012-03-01 24 views
12

tập tin XML này được đặt tên example.xml:Python: ElementTree, có được chuỗi namespace của một Element

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

Nếu tôi tải example.xml và phân tích nó với ElementTree tôi có thể nhìn thấy không gian tên của nó là 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> 

tôi đã không tìm thấy một phương pháp để gọi điện để nhận được chỉ là không gian tên từ một Element mà không cần đến phân tích cú pháp str(an_element) của một Element. Có vẻ như phải có một cách tốt hơn.

+0

bạn có biết cách sử dụng phương pháp tìm trong trường hợp này không? nó không hoạt động ở đây ... – caarlos0

Trả lời

10

Tôi không chắc chắn nếu điều này là có thể với xml.etree, nhưng đây là cách bạn có thể làm điều đó với lxml.etree:

>>> from lxml import etree 
>>> tree = etree.parse('example.xml') 
>>> tree.xpath('namespace-uri(.)') 
'http://maven.apache.org/POM/4.0.0' 
+1

Tôi nhận được 'chưa được giải quyết nhập khẩu: etree' bằng cách sử dụng Python 2.7.2 trong Windows. 'xpath' không có sẵn như là một phương thức khi sử dụng' xml.etree' và nếu tôi sử dụng 'find()' (hỗ trợ các biểu thức xpath) thì câu lệnh 'namespace-uri (.) '' vẫn không hoạt động. – Deleted

+0

đây là chính xác những gì tôi đang tìm kiếm, [xem pr trên gh] (https://github.com/samatjain/gpxsplitter/pull/3) –

+0

Đây là giải pháp tốt nhất mà tôi đã nhìn thấy. Tôi thường sử dụng xmlstarlet nhưng bây giờ tôi có thể chuyển đổi. –

1

Tôi nghĩ rằng nó sẽ được dễ dàng hơn để có một cái nhìn tại các thuộc tính:

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

Chắc chắn dễ dàng hơn việc phân tích cú pháp 'str (the_element)'. Nhưng tôi đoán phân tích 'the_element.tag' thậm chí còn dễ dàng hơn một chút. Vì tôi chỉ quan tâm đến không gian tên. Bạn nghĩ sao? – Deleted

+1

Tôi nghĩ rằng câu trả lời của @ RikPoggi có vẻ là câu trả lời hay nhất (thực ra, tôi đã upvoted nó). Trong thực tế, việc nhận được không gian tên nên dễ dàng như 're.search ('\ {(. *) \}', The_element.tag) .group (1)'. Với câu trả lời của tôi có vẻ như bạn có thể sử dụng 'the_element.attrib.values ​​() [0] .split() [0]', nhưng, quả thật vậy, nó trông không đơn giản lắm và nó không được đảm bảo rằng bạn đã thắng ' t nhận được bất kỳ thuộc tính nào khác trong tương lai. – jcollado

12

Đây là nhiệm vụ hoàn hảo cho regular expression.

import re 

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

Sau khi chiến đấu trong một thời gian với vấn đề này, đây là giải pháp tốt nhất tôi tìm thấy. Tôi không thể tin rằng API không giúp bạn có được một cách để yêu cầu không gian tên và, đồng thời, nó không trả về thuộc tính 'xmlns' khi thực hiện 'rootElement.keys()'. Chắc chắn có một lý do chính đáng cho điều đó nhưng tôi không thể tìm thấy nó vào lúc này. – Robert

5

Nếu không sử dụng biểu thức thông thường:

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

một câu trả lời tương tự 'root.tag [1: root.tag.index ('}')]' – watashiSHUN

0

yếu tố Các lxml.xtree thư viện có một cuốn từ điển được gọi là nsmap, trong đó cho thấy tất cả các không gian tên đó đang được sử dụng trong phạm vi thẻ hiện hành.

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

Câu trả lời ngắn gọn là:

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

nhưng chỉ nếu bạn đã được gọi

ElementTree.register_namespace(prefix,uri) 

để đáp ứng với mỗi sự kiện == "start-ns" nhận trong khi lặp thông qua kết quả của

ET.iterparse(...) 

và bạn đăng ký "start-ns"

Câu trả lời cho câu hỏi "không gian tên mặc định là gì?", Nó là cần thiết để làm rõ hai điểm:

(1) chi tiết kỹ thuật XML nói rằng không gian tên mặc định không nhất thiết là toàn cục trên cây, thay vì không gian tên mặc định có thể được khai báo lại ở bất kỳ phần tử nào dưới gốc và kế thừa xuống cho đến khi gặp lại khai báo lại không gian tên mặc định khác.

(2) Mô-đun ElementTree có thể xử lý các tài liệu giống như XML không có không gian tên mặc định gốc, -if- chúng không sử dụng không gian tên ở bất kỳ đâu trong tài liệu. (* có thể có điều kiện ít nghiêm ngặt hơn, ví dụ:, đó là "nếu" và không nhất thiết phải "iff").

Có lẽ cũng đáng xem xét "bạn muốn nó làm gì?" Hãy xem xét rằng các tệp XML có thể tương đương ngữ nghĩa, nhưng cú pháp rất khác nhau. Ví dụ: ba tệp sau đây tương đương ngữ nghĩa, nhưng A.xml có một khai báo không gian tên mặc định, B.xml có ba và C.xml không có.

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> 

Tệp C.xml là biểu diễn cú pháp mở rộng chuẩn được trình bày cho chức năng tìm kiếm ElementTree.

Nếu bạn chắc chắn một tiên nghiệm rằng sẽ không có sự va chạm không gian tên, bạn có thể sửa đổi các thẻ yếu tố trong khi phân tích như đã thảo luận ở đây: Python ElementTree module: How to ignore the namespace of XML files to locate matching element when using the method "find", "findall"

0

kết hợp một số các câu trả lời ở trên, tôi nghĩ rằng các mã ngắn nhất là

theroot = tree.getroot() 
theroot.attrib[theroot.keys()[0]] 
Các vấn đề liên quan