2011-07-27 10 views
12

में ElementTree साथ तत्व निकाल मैं एक XML दस्तावेज जिसमें मैं कुछ तत्वों के लिए खोज करना चाहते हैं और अगर वे कुछ मानदंड से मेल खाते हैं मैं उन्हें नष्ट करनेखोज और अजगर

हालांकि चाहते हैं, मैं सक्षम होने के लिए नहीं कर पा रहे तत्वों के जनक का उपयोग करने के लिए इतना है कि मैं इसे

file = open('test.xml', "r") 
elem = ElementTree.parse(file) 

namespace = "{http://somens}" 

props = elem.findall('.//{0}prop'.format(namespace)) 
for prop in props: 
    type = prop.attrib.get('type', None) 
    if type == 'json': 
     value = json.loads(prop.attrib['value']) 
     if value['name'] == 'Page1.Button1': 
      #here I need to access the parent of prop 
      # in order to delete the prop 

वहाँ एक रास्ता मैं यह कर सकता है नष्ट कर सकते हैं?

धन्यवाद

उत्तर

13

आप अनुसार remove विधि के साथ बच्चे तत्वों निकाल सकते हैं। किसी तत्व को निकालने के लिए आपको अपने माता-पिता को remove विधि कॉल करना होगा। दुर्भाग्य से Element अपने माता-पिता के लिए एक संदर्भ प्रदान नहीं करता है, तो यह आप पर निर्भर है माता पिता/बच्चे संबंधों का ट्रैक

(जो elem.findall() के आपके उपयोग के खिलाफ बोलता है) रखने के लिए एक प्रस्तावित समाधान ऐसा दिखाई दे सकता:

root = elem.getroot() 
for child in root: 
    if child.name != "prop": 
     continue 
    if True:# TODO: do your check here! 
     root.remove(child) 

पीएस: prop.attrib.get() का उपयोग न करें, prop.get() का उपयोग करें, जैसा कि here समझाया गया है।

+0

मैं देखता हूं। मैं lxml पर भी एक नज़र डाल रहा हूं जो मैंने पढ़ा है, तत्व के माता-पिता तक पहुंच प्रदान करता है। धन्यवाद वैसे भी – Thomas

+3

हाँ, यह सही है। एलएक्सएमएल सामान्य रूप से इंटरफेस की तुलना में अधिक सुविधाओं के साथ 'एलिमेंट ट्री' कार्यान्वयन प्रदान करता है। एलएक्सएमएल में 'एलिमेंट' क्लास माता-पिता तत्व का संदर्भ प्राप्त करने के लिए 'getparent()' विधि प्रदान करती है। – Constantinius

+2

क्या होगा यदि मूल तत्व रूट से गहरा एक तत्व से अधिक है? क्या होगा यदि यह परिवर्तनीय गहराई पर है? – dwjohnston

2

आप एलीमेंट के माता-पिता का चयन करने के लिए xpath का उपयोग कर सकते हैं।

file = open('test.xml', "r") 
elem = ElementTree.parse(file) 

namespace = "{http://somens}" 

props = elem.findall('.//{0}prop'.format(namespace)) 
for prop in props: 
    type = prop.get('type', None) 
    if type == 'json': 
     value = json.loads(prop.attrib['value']) 
     if value['name'] == 'Page1.Button1': 
      # Get parent and remove this prop 
      parent = prop.find("..") 
      parent.remove(prop) 

http://docs.python.org/2/library/xml.etree.elementtree.html#supported-xpath-syntax

छोड़कर अगर आप कोशिश है कि यह काम नहीं करता है: तो बजाय http://elmpowered.skawaii.net/?p=74

आपके पास करने के लिए:

file = open('test.xml', "r") 
elem = ElementTree.parse(file) 

namespace = "{http://somens}" 
search = './/{0}prop'.format(namespace) 

# Use xpath to get all parents of props  
prop_parents = elem.findall(search + '/..') 
for parent in prop_parents: 
    # Still have to find and iterate through child props 
    for prop in parent.findall(search): 
     type = prop.get('type', None) 
     if type == 'json': 
      value = json.loads(prop.attrib['value']) 
      if value['name'] == 'Page1.Button1': 
       parent.remove(prop) 

यह दो खोजों और एक नेस्टेड है पाश। आंतरिक खोज केवल उन तत्वों पर होती है जिन्हें प्रोप को पहले बच्चों के रूप में जाना जाता है, लेकिन इसका मतलब आपकी स्कीमा के आधार पर ज्यादा नहीं हो सकता है।

1

इस तथ्य का उपयोग करके कि प्रत्येक बच्चे के माता-पिता होने चाहिए, मैं @ kitsu.eb के उदाहरण को सरल बनाने जा रहा हूं। बच्चों और माता-पिता को पाने के लिए findall कमांड का उपयोग करके, उनके सूचकांक बराबर होंगे।

file = open('test.xml', "r") 
    elem = ElementTree.parse(file) 

    namespace = "{http://somens}" 
    search = './/{0}prop'.format(namespace) 

    # Use xpath to get all parents of props  
    prop_parents = elem.findall(search + '/..') 

    props = elem.findall('.//{0}prop'.format(namespace)) 
    for prop in props: 
      type = prop.attrib.get('type', None) 
      if type == 'json': 
       value = json.loads(prop.attrib['value']) 
       if value['name'] == 'Page1.Button1': 
        #use the index of the current child to find 
        #its parent and remove the child 
        prop_parents[props.index[prop]].remove(prop) 
0

मुझे पता है कि यह एक पुराना धागा है, लेकिन यह एक समान कार्य को समझने की कोशिश कर रहा था, जबकि यह पॉप-अप रहा। मुझे दो कारणों से स्वीकृत उत्तर पसंद नहीं आया:

1) यह टैग के कई घोंसला वाले स्तरों को संभाल नहीं करता है।

2) यदि एक ही स्तर पर एक ही स्तर पर एकाधिक एक्सएमएल टैग हटा दिए जाते हैं तो यह टूट जाएगा। चूंकि प्रत्येक तत्व Element._children का सूचकांक है, इसलिए इसे अग्रेषित करने के दौरान आपको हटा नहीं देना चाहिए।

मुझे लगता है कि एक बेहतर और अधिक बहुमुखी समाधान यह है:

import xml.etree.ElementTree as et 
file = 'test.xml' 
tree = et.parse(file) 
root = tree.getroot() 

def iterator(parents, nested=False): 
    for child in reversed(parents): 
     if nested: 
      if len(child) >= 1: 
       iterator(child) 
     if True: # Add your entire condition here 
      parents.remove(child) 

iterator(root, nested=True) 

ओपी के लिए, यह काम करना चाहिए - लेकिन मैं डेटा आप के साथ काम कर रहे हैं तो यह एकदम सही है परीक्षण करने के लिए नहीं है।

import xml.etree.ElementTree as et 
file = 'test.xml' 
tree = et.parse(file) 

namespace = "{http://somens}" 
props = tree.findall('.//{0}prop'.format(namespace)) 

def iterator(parents, nested=False): 
    for child in reversed(parents): 
     if nested: 
      if len(child) >= 1: 
       iterator(child) 
     if prop.attrib.get('type') == 'json': 
      value = json.loads(prop.attrib['value']) 
      if value['name'] == 'Page1.Button1': 
       parents.remove(child) 

iterator(props, nested=True) 
0

मुझे इस प्रकार के फ़िल्टरिंग के लिए XPath अभिव्यक्ति का उपयोग करना पसंद है। जब तक मैं अन्यथा नहीं जानता, ऐसी अभिव्यक्ति को मूल स्तर पर लागू किया जाना चाहिए, जिसका अर्थ है कि मैं केवल माता-पिता नहीं प्राप्त कर सकता हूं और उस अभिभावक पर समान अभिव्यक्ति लागू नहीं कर सकता। हालांकि, मुझे ऐसा लगता है कि एक अच्छा और लचीला समाधान है जो किसी भी समर्थित XPath के साथ काम करना चाहिए, जब तक कि कोई भी मांग नोड रूट न हो। यह इस तरह कुछ जाता है:

root = elem.getroot() 
# Find all nodes matching the filter string (flt) 
nodes = root.findall(flt) 
while len(nodes): 
    # As long as there are nodes, there should be parents 
    # Get the first of all parents to the found nodes 
    parent = root.findall(flt+'/..')[0] 
    # Use this parent to remove the first node 
    parent.remove(nodes[0]) 
    # Find all remaining nodes 
    nodes = root.findall(flt) 
संबंधित मुद्दे