কীভাবে এলএক্সএমএল-তে একটি উপাদান সরাবেন


85

পাইথনের এলএক্সএমএল ব্যবহার করে কোনও অ্যাট্রিবিউটর বিষয়বস্তুর উপর ভিত্তি করে উপাদানগুলি আমাকে সম্পূর্ণরূপে অপসারণ করতে হবে। উদাহরণ:

import lxml.etree as et

xml="""
<groceries>
  <fruit state="rotten">apple</fruit>
  <fruit state="fresh">pear</fruit>
  <fruit state="fresh">starfruit</fruit>
  <fruit state="rotten">mango</fruit>
  <fruit state="fresh">peach</fruit>
</groceries>
"""

tree=et.fromstring(xml)

for bad in tree.xpath("//fruit[@state=\'rotten\']"):
  #remove this element from the tree

print et.tostring(tree, pretty_print=True)

আমি এটি মুদ্রণ করতে চাই:

<groceries>
  <fruit state="fresh">pear</fruit>
  <fruit state="fresh">starfruit</fruit>
  <fruit state="fresh">peach</fruit>
</groceries>

কোনও অস্থায়ী পরিবর্তনশীল সংরক্ষণ না করে নিজে নিজে এটিতে মুদ্রণ না করে কি উপায় আছে:

newxml="<groceries>\n"
for elt in tree.xpath('//fruit[@state=\'fresh\']'):
  newxml+=et.tostring(elt)

newxml+="</groceries>"

উত্তর:


155

removeএকটি এক্সএমএল উপাদান ব্যবহার করুন :

tree=et.fromstring(xml)

for bad in tree.xpath("//fruit[@state=\'rotten\']"):
  bad.getparent().remove(bad)     # here I grab the parent of the element to call the remove directly on it

print et.tostring(tree, pretty_print=True, xml_declaration=True)

যদি আমাকে @ আকরন সংস্করণটির সাথে তুলনা করতে হয় তবে সরানো উপাদানগুলি আপনার এক্সএমএল এর মূল নোডের নীচে না থাকলেও খনি কাজ করবে।


4
আপনি এই উত্তর এবং অ্যাকর্ন দ্বারা সরবরাহিত একটির মধ্যে পার্থক্য সম্পর্কে মন্তব্য করতে পারেন?
ইওক

এটি একটি লজ্জার বিষয় যে এলিমেন্ট শ্রেণীর কোনও 'পপ' পদ্ধতি নেই।
পূজামজি

29

আপনি removeফাংশনটি সন্ধান করছেন। গাছের অপসারণের পদ্ধতিটি কল করুন এবং এটিকে অপসারণের জন্য একটি উত্তমরূপটি দিন।

import lxml.etree as et

xml="""
<groceries>
  <fruit state="rotten">apple</fruit>
  <fruit state="fresh">pear</fruit>
  <punnet>
    <fruit state="rotten">strawberry</fruit>
    <fruit state="fresh">blueberry</fruit>
  </punnet>
  <fruit state="fresh">starfruit</fruit>
  <fruit state="rotten">mango</fruit>
  <fruit state="fresh">peach</fruit>
</groceries>
"""

tree=et.fromstring(xml)

for bad in tree.xpath("//fruit[@state='rotten']"):
    bad.getparent().remove(bad)

print et.tostring(tree, pretty_print=True)

ফলাফল:

<groceries>
  <fruit state="fresh">pear</fruit>
  <fruit state="fresh">starfruit</fruit>
  <fruit state="fresh">peach</fruit>
</groceries>

আপনি আমার জন্য সবেমাত্র সমস্ত lxML- সম্পর্কিত উত্তর পেয়েছেন, তাই না? ;-)
ইওক

আপনি এই উত্তর এবং সিড্রিকের সরবরাহিত একটির মধ্যে পার্থক্য সম্পর্কে মন্তব্য করতে পারেন?
ইওক

4
আহ, আমি যে বিষয়টিকে .remove()ডাকতে চাইছি সে উপাদানটির একটি শিশু হওয়া প্রয়োজন বলে আমি এটিকে উপেক্ষা করেছি । সুতরাং আপনি যে উপাদানটি সরাতে চান তার পিতামাতার সাথে এটি কল করা দরকার। উত্তর সংশোধন করা হয়েছে।
আকরেন

@ আকর্ন: এটি, যদি সরানোর উপাদানটি সরাসরি মূল নোডের নীচে না থাকে তবে এটি ব্যর্থ হত।
ক্যাড্রিক জুলিয়েন

17
@ ইওক: আমার চেয়ে ১ সেকেন্ড আগে উত্তর দিয়েছিলেন বলে সিড্রিককে মেনে নিন , এবং আরও বড় কথা, তাঁর উত্তরটি সঠিক ছিল :)
অ্যাকর্ন

14

আমি একটি পরিস্থিতি পূরণ করেছি:

<div>
    <script>
        some code
    </script>
    text here
</div>

div.remove(script)text hereআমি যে অংশটি বোঝাতে চাইনি সে অংশটি সরিয়ে ফেলবে ।

এখানে উত্তর অনুসরণ করে , আমি এটি আমার etree.strip_elementsজন্য একটি ভাল সমাধান, যা আপনি with_tail=(bool)প্যারামের সাহায্যে পিছনে লেখাটি সরিয়ে ফেলবেন কিনা তা নিয়ন্ত্রণ করতে পারেন found

তবে এখনও আমি জানি না যে এটি ট্যাগের জন্য এক্সপথ ফিল্টার ব্যবহার করতে পারে কিনা। শুধু তথ্য দেওয়ার জন্য এই রাখুন।

এখানে ডক:

স্ট্রিপ_এলিমেন্টস (ট্রি_অর_ইলিমেন্ট, * ট্যাগ_নাম, সাথে_ টেইল = সত্য)

একটি গাছ বা সাবট্রি থেকে প্রদত্ত ট্যাগ নামের সমস্ত উপাদান মুছুন। এটি তাদের সমস্ত বৈশিষ্ট্য, পাঠ্য সামগ্রী এবং বংশধর সহ উপাদানগুলি এবং তাদের সম্পূর্ণ সাবট্রিটি সরিয়ে ফেলবে। আপনি with_tailকীওয়ার্ড আর্গুমেন্ট অপশনকে স্পষ্টতই মিথ্যাতে সেট না করলে এটি উপাদানটির লেজ পাঠ্যও সরিয়ে ফেলবে ।

ট্যাগের নামগুলিতে যেমন ওয়াইল্ডকার্ড থাকতে পারে _Element.iter

মনে রাখবেন যে এটি মেলে এমনকি আপনার পাস করা উপাদান (বা এলিমেন্ট্রি রুট উপাদান) মুছবে না। এটি কেবল তার বংশধরদের সাথে আচরণ করবে। আপনি যদি মূল উপাদানটি অন্তর্ভুক্ত করতে চান তবে এই ফাংশনটি কল করার আগে সরাসরি তার ট্যাগের নামটি পরীক্ষা করুন।

ব্যবহারের উদাহরণ ::

   strip_elements(some_element,
       'simpletagname',             # non-namespaced tag
       '{http://some/ns}tagname',   # namespaced tag
       '{http://some/other/ns}*'    # any tag from a namespace
       lxml.etree.Comment           # comments
       )

2

ইতিমধ্যে উল্লিখিত হিসাবে, আপনি remove()গাছ থেকে উপ (উপ) উপাদানগুলি মুছতে পদ্ধতিটি ব্যবহার করতে পারেন :

for bad in tree.xpath("//fruit[@state=\'rotten\']"):
  bad.getparent().remove(bad)

তবে এটি tailHTML সহ মিক্সড-কন্টেন্টের ডকুমেন্টগুলি প্রসেস করতে থাকলে এটির মতো উপাদানগুলি সরিয়ে দেয় :

<div><fruit state="rotten">avocado</fruit> Hello!</div>

হয়ে যায়

<div></div>

কোনটি আমি মনে করি আপনি যা সর্বদা চান না :) আমি কেবলমাত্র উপাদানটি সরাতে এবং এর লেজ রাখার জন্য সহায়ক ফাংশন তৈরি করেছি:

def remove_element(el):
    parent = el.getparent()
    if el.tail.strip():
        prev = el.getprevious()
        if prev:
            prev.tail = (prev.tail or '') + el.tail
        else:
            parent.text = (parent.text or '') + el.tail
    parent.remove(el)

for bad in tree.xpath("//fruit[@state=\'rotten\']"):
    remove_element(bad)

এইভাবে এটি লেজ পাঠ্য রাখবে:

<div> Hello!</div>

4
পরীক্ষা করুন el.tail is not None, যেমন একটি কেস হতে পারে।
আইভিডাস ভিলিনস্কাস

1

আপনি এটি সমাধান করতে lxML থেকে এইচটিএমএল ব্যবহার করতে পারেন:

from lxml import html

xml="""
<groceries>
  <fruit state="rotten">apple</fruit>
  <fruit state="fresh">pear</fruit>
  <fruit state="fresh">starfruit</fruit>
  <fruit state="rotten">mango</fruit>
  <fruit state="fresh">peach</fruit>
</groceries>
"""

tree = html.fromstring(xml)

print("//BEFORE")
print(html.tostring(tree, pretty_print=True).decode("utf-8"))

for i in tree.xpath("//fruit[@state='rotten']"):
    i.drop_tree()

print("//AFTER")
print(html.tostring(tree, pretty_print=True).decode("utf-8"))

এটি এই আউটপুট করা উচিত:

//BEFORE
<groceries>
  <fruit state="rotten">apple</fruit>
  <fruit state="fresh">pear</fruit>
  <fruit state="fresh">starfruit</fruit>
  <fruit state="rotten">mango</fruit>
  <fruit state="fresh">peach</fruit>
</groceries>


//AFTER
<groceries>

  <fruit state="fresh">pear</fruit>
  <fruit state="fresh">starfruit</fruit>

  <fruit state="fresh">peach</fruit>
</groceries>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.