2015-12-04 19 views
5

Làm thế nào tôi có thể yêu cầu ElementTree bỏ qua các không gian tên trong một tệp XML? Ví dụ: Tôi muốn truy vấn modelVersion (như trong tuyên bố 1) thay vì {http://maven.apache.org/POM/4.0.0}modelVersion (như trong tuyên bố 2).Python: bỏ qua các không gian tên trong xml.etree.ElementTree?

pom=""" 
<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>4.0.0</modelVersion> 
</project> 
""" 

from xml.etree import ElementTree 
ElementTree.register_namespace("","http://maven.apache.org/POM/4.0.0") 
root = ElementTree.fromstring(pom) 

print 1,root.findall('modelVersion') 
print 2,root.findall('{http://maven.apache.org/POM/4.0.0}modelVersion') 

1 [] 
2 [<Element '{http://maven.apache.org/POM/4.0.0}modelVersion' at 0x1006bff10>] 
+1

AFAIK không phải là cách dễ dàng + sạch sẽ o, đặc biệt là nếu bạn không có khả năng giao dịch với nhiều không gian tên. Có vẻ là một câu hỏi trùng lặp [ở đây] (http://stackoverflow.com/q/13412496/20670), nhưng tôi sẽ không sử dụng dupehammer của tôi nếu bạn nói rằng những cách tiếp cận đó sẽ không hoạt động cho bạn (chúng là loại trông giống như hacks bẩn với tôi). –

+0

Ngoài ra, ['lxml' có thể đáng xem xét] (http://stackoverflow.com/q/14853243/20670), nhưng nó không phải là một phần của thư viện chuẩn. –

+1

thật đáng tiếc là tôi đang gửi cho người không thể cài đặt lxml. Tôi hy vọng thư viện chuẩn kết hợp nó một ngày nào đó. Tôi đã đăng giải pháp hiện tại của mình khiến tôi rất buồn khi tôi nói với mẹ tôi rằng tôi là một lập trình viên chuyên nghiệp. : -/ –

Trả lời

0

Dường như không có đường dẫn thẳng về phía trước, vì vậy, tôi chỉ cần thực hiện các cuộc gọi tìm kiếm, ví dụ:

from xml.etree import ElementTree as ET 

POM = """ 
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="http://maven.apache.org/POM/4.0.0"> 
    <modelVersion>4.0.0</modelVersion> 
</project> 
""" 

NSPS = {'foo' : "http://maven.apache.org/POM/4.0.0"} 

# sic! 
def findall(node, tag): 
    return node.findall('foo:' + tag, NSPS) 

root = ET.fromstring(POM) 
print(map(ET.tostring, findall(root, 'modelVersion'))) 

đầu ra:

['<ns0:modelVersion xmlns:ns0="http://maven.apache.org/POM/4.0.0">4.0.0</ns0:modelVersion>\n'] 
0

Dưới đây là những gì tôi đang hiện đang làm, mà làm cho tôi vô cùng tự tin rằng có một cách tốt hơn.

$ cat pom.xml | 
    tr '\n' ' ' | 
    sed 's/<project [^>]*>/<project>/' | 
    myprogram | 
    sed 's/<project>/<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">/' 
+0

thay vì sed'ing nó trong một đường ống, bạn có thể vá chuỗi xml trong kịch bản python hoặc tạo ra một không gian tên giả và một hàm wrapper (pls c câu trả lời của tôi dưới đây) –

+0

Tôi thích sửa nó trong ống coz sau đó chương trình thực tế của tôi là gọn gàng. Nếu tôi có thể chuyển sang gói xml tốt hơn trong tương lai, tôi sẽ chỉ có thể thả nội dung trong trình bao bọc. –

+0

Vâng - nếu bạn đã khá hài lòng với đường ống của bạn - chính xác thì chúng ta đang nói về cái gì :)? –

0

Thay vì bỏ qua, cách tiếp cận khác sẽ được loại bỏ các không gian tên trong cây, do đó không cần phải 'bỏ qua' bởi vì họ không có - xem câu trả lời nonagon cho câu hỏi này (và phần mở rộng của tôi về điều đó để bao gồm các không gian tên trên các thuộc tính): Python ElementTree module: How to ignore the namespace of XML files to locate matching element when using the method "find", "findall"

0

Đây là giải pháp tương đương mà không cần sử dụng trình bao. Ý tưởng cơ bản:

  • dịch <project junk...>-<project>
  • thực hiện "sạch" xử lý mà không cần lo lắng về không gian tên
  • dịch <project> trở lại <project junk...>

với mã mới:

pom=""" 
<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>4.0.0</modelVersion> 
</project> 
""" 
short_project="""<project>""" 
long_project="""<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">""" 

import re,sys 
from xml.etree import ElementTree 

# eliminate namespace specs 
pom=re.compile('<project [^>]*>').sub(short_project,pom) 

root = ElementTree.fromstring(pom) 
ElementTree.dump(root) 
print 1,root.findall('modelVersion') 
print 2,root.findall('{http://maven.apache.org/POM/4.0.0}modelVersion') 
mv=root.findall('modelVersion') 

# restore the namespace specs 
pom=ElementTree.tostring(root) 
pom=re.compile(short_project).sub(long_project,pom) 
Các vấn đề liên quan