2011-10-26 5 views
18

की समतुल्यता का परीक्षण करना मुझे दो एक्सएमएल तत्वों के समतुल्यता में रूचि है; और मैंने पाया है कि तत्वों के टोस्टरिंग का परीक्षण करना; हालांकि, यह हैकी लगता है। क्या दो एट्री तत्वों के समानता का परीक्षण करने का एक बेहतर तरीका है? उदाहरण:xml.etree.ElementTree

import xml.etree.ElementTree as etree 
h1 = etree.Element('hat',{'color':'red'}) 
h2 = etree.Element('hat',{'color':'red'}) 

h1 == h2 

झूठी

etree.tostring(h1) == etree.tostring(h2) 

सच

+0

दो तत्वों की तुलना करने के लिए एक समारोह में पाया जा सकता [Itamar के जवाब] (http://stackoverflow.com/a/24349916/2371522) नीचे । – One

उत्तर

0

सोने नहीं थाली करो। आपके पास एक अच्छी तुलना है। अंत में एक्सएमएल यह टेक्स्ट है।

+0

हां, और यदि आप फ़ॉर्मेटिंग के बारे में चिंतित हैं, तो ईटी में कनवर्ट करें, फिर स्ट्रिंग और तुलना करने के लिए डंप करें। – Wyrmwood

2

जटिल संरचनाओं की तुलना करने का एक सामान्य तरीका उन्हें एक सामान्य अद्वितीय पाठपरक प्रतिनिधित्व में डंप करना और परिणामी तारों की तुलना समानता के लिए करना है।

दो प्राप्त जेसन स्ट्रिंग की तुलना करने के लिए, आप उन्हें जेसन ऑब्जेक्ट्स में परिवर्तित कर देंगे, और फिर उन्हें वापस स्ट्रिंग्स (उसी कनवर्टर के साथ) में परिवर्तित करें और तुलना करें। मैंने जेसन फ़ीड की जांच करने के लिए यह किया, यह अच्छी तरह से काम करता है।

एक्सएमएल के लिए, यह लगभग समान है, लेकिन आपको ".text" भागों (पाठ, खाली या नहीं, जो टैग के बाहर पाया जा सकता है) को संभालना पड़ सकता है (स्ट्रिप? निकालें?)।

तो संक्षेप में, आपका समाधान एक हैक नहीं है, जब तक आप सुनिश्चित करते हैं कि दो समकक्ष एक्सएमएल (आपके संदर्भ के अनुसार) में एक ही स्ट्रिंग प्रस्तुति होगी।

3

मान लीजिए कि वास्तव में दो नोड्स की तुलना करने के लिए सबसे अच्छा तरीका नहीं है यदि आप नहीं जानते कि प्रत्येक बच्चे के पास कितने बच्चे हो सकते हैं और आप सभी बच्चों को खोज में शामिल करना चाहते हैं।

बेशक

, अगर आप बस एक आप प्रदर्शन कर रहे हैं की तरह एक निःसंतान नोड है, तो आप बस टैग, attrib तुलना कर सकते हैं, और पूंछ गुण:

if h1.tag == h2.tag and h1.attrib == h2.attrib and h1.tail == h2.tail: 
    print("h1 and h2 are the same") 
else 
    print("h1 and h2 are the different") 

मैं के किसी भी प्रमुख लाभ नहीं दिख रहा है हालांकि, टोस्टिंग का उपयोग करने पर यह।

+0

आप अपनी आवश्यकताओं के अनुसार पाठ में भी फेंक सकते हैं: 'h1.text == h2.text' – bmaupin

+0

यह तत्वों की तुलना बच्चों की तुलना नहीं करता है ... – drevicko

7

तारों की तुलना करना हमेशा काम नहीं करता है। गुणों का क्रम दो नोड्स समकक्ष पर विचार करने के लिए कोई फर्क नहीं पड़ता। हालांकि, यदि आप स्ट्रिंग तुलना करते हैं, तो ऑर्डर स्पष्ट रूप से मायने रखता है।

>>> from lxml import etree 
>>> h1 = etree.XML('<hat color="blue" price="39.90"/>') 
>>> h2 = etree.XML('<hat price="39.90" color="blue"/>') 
>>> etree.tostring(h1) == etree.tostring(h2) 
False 

यह:

मुझे यकीन है कि अगर यह एक समस्या है या एक सुविधा है, लेकिन lxml.etree की मेरी संस्करण विशेषताओं के आदेश को बरकरार रखता है अगर वे एक फ़ाइल या एक स्ट्रिंग से पार्स कर रहे हैं नहीं कर रहा हूँ संस्करण-निर्भर हो सकता है (मैं पाइथन 2.7.3 का उपयोग lxml.etree 2.3.2 के साथ उबंटू पर करता हूं); मुझे याद है कि जब मैं (पठनीयता कारणों के लिए) चाहता था, तो मुझे एक साल पहले विशेषताओं के क्रम को नियंत्रित करने का कोई तरीका नहीं मिला।

जैसा कि मुझे विभिन्न धारावाहिकों द्वारा उत्पादित XML फ़ाइलों की तुलना करने की आवश्यकता है, मुझे टैग, टेक्स्ट, विशेषताओं और प्रत्येक नोड के बच्चों की तुलना करने की तुलना में कोई अन्य तरीका नहीं दिखता है। और निश्चित रूप से पूंछ, अगर वहाँ कुछ दिलचस्प है। lxml और xml.etree.ElementTree

सत्य का

तुलना में यह कार्यान्वयन निर्भर हो सकता है। जाहिर है, एलएक्सएमएल आदेशित आदेश या कुछ ऐसा मानक मानक xml.etree का उपयोग करता है।ElementTree विशेषताओं का क्रम बनाए रखने नहीं करता है: (। हाँ, नई पंक्तियां याद कर रहे हैं लेकिन यह एक छोटी सी समस्या है।)

Python 2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from lxml import etree 
>>> h1 = etree.XML('<hat color="blue" price="39.90"/>') 
>>> h2 = etree.XML('<hat price="39.90" color="blue"/>') 
>>> etree.tostring(h1) == etree.tostring(h2) 
False 
>>> etree.tostring(h1) 
'<hat color="blue" price="39.90"/>' 
>>> etree.tostring(h2) 
'<hat price="39.90" color="blue"/>' 
>>> etree.dump(h1) 
<hat color="blue" price="39.90"/>>>> etree.dump(h2) 
<hat price="39.90" color="blue"/>>>> 

>>> import xml.etree.ElementTree as ET 
>>> h1 = ET.XML('<hat color="blue" price="39.90"/>') 
>>> h1 
<Element 'hat' at 0x2858978> 
>>> h2 = ET.XML('<hat price="39.90" color="blue"/>') 
>>> ET.dump(h1) 
<hat color="blue" price="39.90" /> 
>>> ET.dump(h2) 
<hat color="blue" price="39.90" /> 
>>> ET.tostring(h1) == ET.tostring(h2) 
True 
>>> ET.dump(h1) == ET.dump(h2) 
<hat color="blue" price="39.90" /> 
<hat color="blue" price="39.90" /> 
True 

एक और सवाल हो सकता है क्या महत्वहीन whan की तुलना माना जाता है। उदाहरण के लिए, कुछ टुकड़ों में अतिरिक्त रिक्त स्थान हो सकते हैं और हम परवाह नहीं करना चाहते हैं। इस तरह, कुछ सीरियलाइजिंग फ़ंक्शन लिखना हमेशा बेहतर होता है जो वास्तव में हमें आवश्यक काम करता है।

+1

'.dump (...)' रिटर्न 'कोई नहीं', तो' ET.dump (h1) == ET.dump (h2) 'वास्तव में' none' से 'none' की तुलना कर रहा है। –

4

सीरियलाइजिंग और deserializing एक्सएमएल के लिए काम नहीं करेगा क्योंकि गुण ऑर्डर निर्भर नहीं हैं (और अन्य कारणों) E.g.

<THING a="foo" b="bar"></THING> 
<THING b="bar" a="foo" /> 

वास्तव में एक तत्व तुलना मुश्किल है कैसे करना है: इन दोनों तत्वों तार्किक ही है, लेकिन अलग तार कर रहे हैं। जहां तक ​​मैं कह सकता हूं, आपके लिए ऐसा करने के लिए एलिमेंट ट्री में कुछ भी नहीं बनाया गया है। मुझे यह करने की ज़रूरत थी, और नीचे दिए गए कोड का इस्तेमाल किया। यह मेरी जरूरतों के लिए काम करता है, लेकिन यह बड़े एक्सएमएल संरचनाओं के लिए उपयुक्त नहीं है और यह तेज़ या कुशल नहीं है! यह एक समानता समारोह के बजाय एक क्रमिक कार्य है, इसलिए 0 का परिणाम बराबर है और कुछ और नहीं है। एक सच्चे या झूठी वापसी समारोह के साथ इसे लपेटना पाठक के लिए एक अभ्यास के रूप में छोड़ दिया गया है!

def cmp_el(a,b): 
    if a.tag < b.tag: 
     return -1 
    elif a.tag > b.tag: 
     return 1 
    elif a.tail < b.tail: 
     return -1 
    elif a.tail > b.tail: 
     return 1 

    #compare attributes 
    aitems = a.attrib.items() 
    aitems.sort() 
    bitems = b.attrib.items() 
    bitems.sort() 
    if aitems < bitems: 
     return -1 
    elif aitems > bitems: 
     return 1 

    #compare child nodes 
    achildren = list(a) 
    achildren.sort(cmp=cmp_el) 
    bchildren = list(b) 
    bchildren.sort(cmp=cmp_el) 

    for achild, bchild in zip(achildren, bchildren): 
     cmpval = cmp_el(achild, bchild) 
     if cmpval < 0: 
      return -1 
     elif cmpval > 0: 
      return 1  

    #must be equal 
    return 0 
+0

दो एक्सएमएल फाइलों की तुलना में समस्या का मुख्य कारण अलग-अलग स्वरूपण जैसा है जो उसने ऊपर कहा था। और, अधिकांश समय पूंछ खंड में रिक्त स्थान या न्यूलाइन में निहित है। परीक्षण के लिए मेरे पास दो तर्कसंगत समान XML फ़ाइलें थीं और कोड को पता नहीं चला कि वे वही हैं। लेकिन, मैंने बस कोड से तुलना की तुलना हटा दी, और यह एक आकर्षण की तरह काम किया! – PMN

18

यह तुलना समारोह मेरे लिए काम करता है:

def elements_equal(e1, e2): 
    if e1.tag != e2.tag: return False 
    if e1.text != e2.text: return False 
    if e1.tail != e2.tail: return False 
    if e1.attrib != e2.attrib: return False 
    if len(e1) != len(e2): return False 
    return all(elements_equal(c1, c2) for c1, c2 in zip(e1, e2)) 
+3

यह एक समाधान है। सुनिश्चित करें कि व्हाइटस्पेस हस्तक्षेप नहीं करता है, उदा। 'etree.XMLParser (remove_blank_text = True) का उपयोग करके। 'सभी() 'में सूची बनाने से बचकर सुधारें। ध्यान दें कि 'lip()' के बाद से 'ज़िप() 'काम किया गया था। – One

+1

साफ! यह तत्व टैग के बावजूद काम करता है, यहां तक ​​कि एक ही टैगनाम वाले तत्वों के लिए भी। – Fredrik