Frage

Ich habe ein folgendes XML-Dokument:

<node0>
    <node1>
      <node2 a1="x1"> ... </node2>
      <node2 a1="x2"> ... </node2>
      <node2 a1="x1"> ... </node2>
    </node1>
</node0>

Ich möchte node2, um herauszufiltern, wenn a1="x2". Der Benutzer stellt die XPath und Attributwerte, die getestet und herausgefiltert müssen. Ich sah einige Lösungen in Python wie BeautifulSoup aber sie sind zu kompliziert und nicht den Fall des Textes bewahren. Ich möchte das Dokument wie zuvor mit einem paar Sachen halten herausgefiltert werden.

Können Sie eine einfache und prägnante Lösung empfehlen? Dies sollte auch nicht von den Blicken von ihm kompliziert sein. Das tatsächliche XML-Dokument ist nicht so einfach, wie oben, aber Idee ist das gleiche.

War es hilfreich?

Lösung

Diese Anwendungen xml.etree.ElementTree, die in der Standardbibliothek ist:

import xml.etree.ElementTree as xee
data='''\
<node1>
  <node2 a1="x1"> ... </node2>
  <node2 a1="x2"> ... </node2>
  <node2 a1="x1"> ... </node2>
</node1>
'''
doc=xee.fromstring(data)

for tag in doc.findall('node2'):
    if tag.attrib['a1']=='x2':
        doc.remove(tag)
print(xee.tostring(doc))
# <node1>
#   <node2 a1="x1"> ... </node2>
#   <node2 a1="x1"> ... </node2>
# </node1>

Diese Anwendungen lxml, die nicht in der Standard-Bibliothek ist, hat aber eine leistungsfähigere Syntax :

import lxml.etree
data='''\
<node1>
  <node2 a1="x1"> ... </node2>
  <node2 a1="x2"> ... </node2>
  <node2 a1="x1"> ... </node2>
</node1>
'''
doc = lxml.etree.XML(data)
e=doc.find('node2/[@a1="x2"]')
doc.remove(e)
print(lxml.etree.tostring(doc))

# <node1>
#   <node2 a1="x1"> ... </node2>
#   <node2 a1="x1"> ... </node2>
# </node1>

Edit: Wenn node2 ist tiefer im xml begraben, dann können Sie alle Tags durchlaufen, überprüfen Sie jeden übergeordneten Tag zu sehen, ob das node2 Element eines seiner Kinder ist, und das Entfernen es wenn ja:

Mit nur xml.etree.ElementTree:

doc=xee.fromstring(data)
for parent in doc.getiterator():
    for child in parent.findall('node2'):
        if child.attrib['a1']=='x2':
            parent.remove(child)

Mit lxml:

doc = lxml.etree.XML(data)
for parent in doc.iter('*'):
    child=parent.find('node2/[@a1="x2"]')
    if child is not None:
        parent.remove(child)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top