تصفية XML مع Python
-
03-10-2019 - |
سؤال
لدي وثيقة XML التالية:
<node0>
<node1>
<node2 a1="x1"> ... </node2>
<node2 a1="x2"> ... </node2>
<node2 a1="x1"> ... </node2>
</node1>
</node0>
اريد التصفية node2
متى a1="x2"
. يوفر المستخدم قيم XPath والسمة التي تحتاج إلى اختبار وتصفيتها. لقد نظرت إلى بعض الحلول في بيثون مثل BeautifulSoup لكنها معقدة للغاية ولا تحافظ على حالة النص. أريد الاحتفاظ بالوثيقة كما كان من قبل مع بعض الأشياء التي تمت تصفيتها.
هل يمكنك أن تنصح بحل بسيط ومختصر؟ هذا لا ينبغي أن يكون معقدًا جدًا من مظهره. وثيقة XML الفعلية ليست بسيطة على النحو الوارد أعلاه ولكن الفكرة هي نفسها.
المحلول
هذا يستخدم xml.etree.ElementTree
التي هي في المكتبة القياسية:
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>
هذا يستخدم lxml
, ، وهي ليست في المكتبة القياسية ، ولكن لديها بناء جملة أكثر قوة:
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>
يحرر: إذا node2
يتم دفنه بعمق أكبر في XML ، ثم يمكنك التكرار من خلال جميع العلامات ، تحقق من كل علامة الوالدين لمعرفة ما إذا كان node2
العنصر هو أحد أطفاله ، وإزالته إذا كان الأمر كذلك:
باستخدام فقط 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)
باستخدام 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)