ElementTree XPath - Seleziona l'elemento in base all'attributo
-
03-07-2019 - |
Domanda
Sto riscontrando problemi nell'uso dell'attributo XPath Selector in ElementTree, che dovrei essere in grado di fare secondo il Documentazione
Ecco un po 'di codice di esempio
XML
<root>
<target name="1">
<a></a>
<b></b>
</target>
<target name="2">
<a></a>
<b></b>
</target>
</root>
Python
def parse(document):
root = et.parse(document)
for target in root.findall("//target[@name='a']"):
print target._children
Ricevo la seguente eccezione:
expected path separator ([)
Soluzione
La sintassi che stai tentando di utilizzare è nuova in ElementTree 1.3 .
Tale versione viene fornita con Python 2.7 o versione successiva. Se hai Python 2.6 o meno hai ancora ElementTree 1.2.6 o meno.
Altri suggerimenti
Esistono diversi problemi in questo codice.
-
ElementTree (in breve) buildin di Python non ha un vero supporto XPATH; solo un sottoinsieme limitato Ad esempio, non supporta le espressioni trova-da-radice come
// target
.Avviso: la documentazione menziona " // " ;, ma solo per i bambini: quindi un'espressione come
.//target
è valido;// ...
non lo è!Esiste un'implementazione alternativa: lxml che è più ricco. È la giuntura che viene utilizzata la documentazione, per il codice incorporato. Ciò non corrisponde / funziona.
-
La notazione
@name
seleziona xml- attributi ; l'espressionekey = value
all'interno di un tag xml.Quindi quel nome-valore deve essere 1 o 2 per selezionare qualcosa nel documento dato. Oppure, si possono cercare target con un elemento 'a' :
target [a]
(no @).
Per il documento dato, analizzato con ElementTree incorporato (v1.3) su root, il codice seguente è corretto e funzionante:
-
root.findall (" .// target ")
Trova entrambi i target -
root.findall (" .// target / a ")
Trova due elementi a -
root.findall (" .// target [a] ")
Questo trova di nuovo entrambi gli elementi target, poiché entrambi hanno un elemento a -
root.findall (" .// target [@ name = '1'] ")
Trova solo il primo target. Si noti che le virgolette intorno a 1 sono necessarie; altrimenti viene generato un SyntaxError -
root.findall (" .// target [a] [@ name = '1'] ")
Anche valido; per trovare quell'obiettivo -
root.findall (" .// target [@ name = '1'] / a ")
Trova solo un elemento a; ...