2015-12-04 14 views
5

Come posso dire a ElementTree di ignorare gli spazi dei nomi in un file XML?Python: ignorando gli spazi dei nomi in xml.etree.ElementTree?

Ad esempio, preferirei interrogare modelVersion (come nella dichiarazione 1) anziché {http://maven.apache.org/POM/4.0.0}modelVersion (come nella dichiarazione 2).

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 non c'è un modo facile + pulito per d o così, soprattutto se non si ha a che fare potenzialmente con più spazi dei nomi. Sembra che ci sia una domanda duplicata [qui] (http://stackoverflow.com/q/13412496/20670), ma non userò il mio dupehammer se dici che quegli approcci non funzioneranno per te (tipo di mi sembra un hacker sporco). –

+0

Inoltre, ['lxml' potrebbe valere la pena di essere esaminato] (http://stackoverflow.com/q/14853243/20670), ma non fa parte della libreria standard. –

+1

purtroppo sto inviando questo a qualcuno che non può installare lxml. Spero che la libreria standard lo incorpori un giorno. Ho pubblicato la mia attuale soluzione che mi rende molto triste coz una volta ho detto a mia madre che ero un programmatore professionista. : -/ –

risposta

0

Non sembra esserci via senza straight-forward, quindi mi piacerebbe semplicemente avvolgere la chiamate Trova, ad esempio

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

uscita:

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

Ecco quello che sto facendo attualmente, il che mi rende incredibilmente sicuro che c'è un modo migliore.

$ 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

invece di metterlo in una pipe, puoi applicare una patch alla stringa xml nello script python o creare uno spazio dei nomi fittizio e una funzione wrapper (pls. C la mia risposta sotto) –

+0

Mi piace aggiustarlo nel pipe coz allora il mio programma attuale è in ordine. Se potrò passare a un pacchetto xml migliore in futuro, sarò in grado di rilasciare le cose nel wrapper. –

+0

Bene - se sei già abbastanza soddisfatto della tua pipa - di cosa stiamo parlando esattamente allora :)? –

0

Ecco la soluzione equivalente senza utilizzare la shell. Idea di base:

  • traducono <project junk...>-<project>
  • eseguire l'elaborazione "pulito", senza preoccuparsi dello spazio dei nomi
  • traducono <project> torna a <project junk...>

con il nuovo codice:

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)