Filtraggio Python Elementtree di XPath

Sep 04 2020

immagina di avere un XML come questo:

<root>
  <elements>
    <element> foo </element>
    <element is="false"> foo </element>
    <element is="false"> bli </element>
    <element is="false"> bla </element>
  </elements>
</root>

Come posso fare questo:

import xml.etree.ElementTree as ET

root = ET.fromstring(XmlFromAbove)
res_a  = root.findall("element[@is='false']")) ##<- This gives me all elements with the specific attribute
res_b  = root.findall("element[not@is='false']")) ##<- This would be nice to give me all elements without that specific attribute (`<element> foo </element>` in this case)

Ora, so che res_bnon funzionerà, ma immagino che questo sia un problema comune, quindi qualcuno ha un'idea di quale sia la soluzione alternativa?

Per sottolineare un po 'di più (copiato dai commenti)

Potrei sicuramente trovare l'elemento contenente "foo", ma quello che voglio sapere è se c'è un modo per trovare qualsiasi elemento che NON contenga l'attributo è = "false".

Risposte

2 balderman Sep 04 2020 at 17:10

vedi sotto

import xml.etree.ElementTree as ET

xml = '''<root>
  <elements>
    <element> foo </element>
    <element is="false"> foo </element>
    <element is="false"> bli </element>
    <element is="false"> bla </element>
    <element please="false"> no_is </element>
    <element is="true"> with_true_is </element>
  </elements>
</root>'''

root = ET.fromstring(xml)

no_is_lst = [e for e in root.findall('.//element') if 'is' not in e.attrib]
for e in no_is_lst:
    print(e.text)

produzione

 foo 
 no_is 
deadshot Sep 04 2020 at 16:59

Puoi usare lxml

from lxml import etree

root = etree.fromstring(data)
res = root.xpath(".//element[not(@is)]")

print(res[0].text) #foo