मुख्य सामग्री पर जाएँ

ElementTree के साथ Python XML ट्यूटोरियल: शुरुआती मार्गदर्शिका

Python ElementTree पैकेज, for लूप्स और XPath अभिव्यक्तियों के साथ XML फ़ाइलों को पार्स, एक्सप्लोर, संशोधित और पॉप्युलेट करना सीखें।
· 10 मि॰ पढ़ें

AI के साथ खोजें

इस ट्यूटोरियल का कोड ऑनलाइन चलाएं और संपादित करें

कोड चलाएं

एक डेटा वैज्ञानिक के रूप में, आप पाएँगे कि XML को समझना वेब-स्क्रैपिंग और संरचित दस्तावेज़ को पार्स करने की सामान्य प्रैक्टिस दोनों के लिए बेहद शक्तिशाली है।

  • आप XML के बारे में और जानेंगे, और आपको Python के ElementTree पैकेज से परिचय कराया जाएगा।
  • फिर, आप जानेंगे कि ElementTree फ़ंक्शंस, for लूप्स और XPath अभिव्यक्तियों की मदद से XML ट्रीज़ को कैसे एक्सप्लोर करें ताकि आप अपने डेटा को बेहतर ढंग से समझ सकें।
  • इसके बाद, आप सीखेंगे कि किसी XML फ़ाइल को कैसे संशोधित किया जाए।
  • आप XML फ़ाइलों को भरने के लिए xpath अभिव्यक्तियों का भी उपयोग करेंगे।

XML क्या है?

XML का अर्थ है "Extensible Markup Language"। इसका मुख्य उपयोग वेबपेजों में होता है, जहाँ डेटा की एक विशिष्ट संरचना होती है और जिसे XML फ़्रेमवर्क द्वारा डायनेमिक रूप से समझा जाता है।

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

  • XML दस्तावेज़ों में  elements कहलाने वाले सेक्शन होते हैं, जिन्हें शुरुआती और समापन tag से परिभाषित किया जाता है। टैग एक मार्कअप कॉन्स्ट्रक्ट है जो < से शुरू और > पर समाप्त होता है। प्रारंभिक और समापन टैग के बीच के अक्षर, यदि कोई हों, तो वे तत्व की सामग्री होते हैं। एलिमेंट्स में अन्य मार्कअप, जिनमें अन्य एलिमेंट्स भी शामिल हो सकते हैं, निहित हो सकते हैं, जिन्हें "child elements" कहा जाता है।
  • सबसे बड़ा, टॉप-लेवल एलिमेंट root कहलाता है, जो अन्य सभी एलिमेंट्स को समाहित करता है।
  • Attributes नाम–मान (name–value) जोड़ी होती हैं जो किसी start-tag या empty-element टैग के भीतर मौजूद रहती हैं। एक XML attribute में केवल एक ही मान हो सकता है और प्रत्येक attribute किसी एलिमेंट पर अधिकतम एक बार ही आ सकता है।

इसे थोड़ा बेहतर समझने के लिए, नीचे दिए गए (संक्षिप्त) XML फ़ाइल पर नज़र डालें:

<?xml version="1.0"?>
<collection>
    <genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back 2 the Future">
               <format multiple="False">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    </genre>

    <genre category="Thriller">
        <decade years="1970s">
            <movie favorite="False" title="ALIEN">
                <format multiple="Yes">DVD</format>
                <year>1979</year>
                <rating>R</rating>
                <description>"""""""""</description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="True" title="Ferris Bueller's Day Off">
                <format multiple="No">DVD</format>
                <year>1986</year>
                <rating>PG13</rating>
                <description>Funny movie about a funny guy</description>
            </movie>
            <movie favorite="FALSE" title="American Psycho">
                <format multiple="No">blue-ray</format>
                <year>2000</year>
                <rating>Unrated</rating>
                <description>psychopathic Bateman</description>
            </movie>
        </decade>
    </genre>

ऊपर जो आपने पढ़ा, उससे आप देखते हैं कि

  • <collection> एकल रूट एलिमेंट है: इसमें अन्य सभी एलिमेंट्स, जैसे <genre> या <movie> शामिल हैं, जो चाइल्ड एलिमेंट्स या सबएलीमेंट्स हैं। जैसा कि आप देख सकते हैं, ये एलिमेंट्स नेस्टेड हैं।

ध्यान दें कि ये चाइल्ड एलिमेंट्स माता-पिता की तरह भी कार्य कर सकते हैं और अपने स्वयं के चाइल्ड एलिमेंट्स रख सकते हैं, जिन्हें तब "सब-चाइल्ड एलिमेंट्स" कहा जाता है।

  • आप देखेंगे कि उदाहरण के लिए <movie> एलिमेंट में favorite title जैसे कुछ "attributes" हैं, जो और भी अधिक जानकारी देते हैं!

XML फ़ाइलों की इस छोटी-सी भूमिका के साथ, आप ElementTree के बारे में और सीखने के लिए तैयार हैं!

ElementTree का परिचय

XML ट्री संरचना प्रोग्रामेटिक रूप से नेविगेशन, संशोधन और हटाने को अपेक्षाकृत सरल बना देती है। Python में एक बिल्ट-इन लाइब्रेरी ElementTree है, जिसमें XMLs (और अन्य समान संरचना वाली फ़ाइलों) को पढ़ने और संशोधित करने के फ़ंक्शंस होते हैं।

पहले, ElementTree इम्पोर्ट करें। ET उपनाम का उपयोग करना सामान्य प्रथा है:

import xml.etree.ElementTree as ET

XML डेटा पार्स करना

दी गई XML फ़ाइल फिल्मों का एक बुनियादी संग्रह बताती है। एकमात्र समस्या यह है कि डेटा बिखरा हुआ है! इस संग्रह के कई अलग-अलग क्यूरेटर्स रहे हैं, और हर किसी का फ़ाइल में डेटा दर्ज करने का अपना तरीका है। इस ट्यूटोरियल का मुख्य लक्ष्य Python के साथ फ़ाइल को पढ़ना और समझना तथा फिर समस्याओं को ठीक करना होगा।

सबसे पहले, आपको ElementTree के साथ फ़ाइल को पढ़ने की आवश्यकता है।

tree = ET.parse('movies.xml')
root = tree.getroot()

अब जब आपने ट्री को इनिशियलाइज़ कर लिया है, तो आपको XML को देखना चाहिए और मान प्रिंट करने चाहिए ताकि आप समझ सकें कि ट्री कैसे संरचित है।

ट्री का हर भाग (रूट सहित) में एक टैग होता है जो एलिमेंट का वर्णन करता है। इसके अतिरिक्त, जैसा कि आपने प्रस्तावना में देखा, एलिमेंट्स के attributes भी हो सकते हैं, जो विशेष रूप से टैग के बार-बार उपयोग के लिए उपयोग किए जाने वाले अतिरिक्त वर्णनकर्ता होते हैं। attributes उस टैग के लिए दर्ज किए गए मानों को वैध ठहराने में भी मदद करते हैं, जो एक बार फिर XML के संरचित फ़ॉर्मेट में योगदान देता है।

आप इस ट्यूटोरियल में आगे देखेंगे कि जब attributes XML में शामिल होते हैं तो वे काफी शक्तिशाली हो सकते हैं!

root.tag
'collection'

टॉप लेवल पर, आप देखते हैं कि यह XML collection टैग में रूटेड है।

root.attrib
{}

तो, रूट के कोई attributes नहीं हैं।

For लूप्स

आप सरल "for" लूप का उपयोग करके रूट के सबएलीमेंट्स (आम तौर पर "children" कहलाते हैं) पर आसानी से इटरेट कर सकते हैं।

for child in root:
    print(child.tag, child.attrib)
genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}

अब आप जानते हैं कि रूट collection के चिल्ड्रन सभी genre हैं। शैली (genre) बताने के लिए, XML category attribute का उपयोग करता है। genre एलिमेंट के अनुसार यहाँ Action, Thriller और Comedy फिल्में हैं।

आम तौर पर पूरे ट्री में मौजूद सभी एलिमेंट्स को जानना सहायक होता है। ऐसा करने के लिए एक उपयोगी फ़ंक्शन root.iter() है। आप इस फ़ंक्शन को "for" लूप में डाल सकते हैं और यह पूरे ट्री पर इटरेट करेगा।

[elem.tag for elem in root.iter()]
['collection',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description']

यह आपको यह सामान्य धारणा देता है कि आपके पास कितने एलिमेंट्स हैं, लेकिन यह ट्री में attributes या लेवल्स नहीं दिखाता।

पूरा दस्तावेज़ देखने का एक सहायक तरीका है। किसी भी एलिमेंट में .tostring() मेथड होता है। यदि आप रूट को .tostring() में पास करते हैं, तो आप पूरा दस्तावेज़ वापस कर सकते हैं। ElementTree (याद रखें कि ET के रूप में एलियस किया गया है) के भीतर, .tostring() थोड़े अलग रूप में आता है।

क्योंकि ElementTree एक शक्तिशाली लाइब्रेरी है जो केवल XML से अधिक इंटरप्रेट कर सकती है। आपको उस स्ट्रिंग के रूप में दिखाए जा रहे दस्तावेज़ की एन्कोडिंग और डिकोडिंग दोनों निर्दिष्ट करनी चाहिए। XMLs के लिए, 'utf8' का उपयोग करें - यह XML के लिए सामान्य दस्तावेज़ फ़ॉर्मेट है।

print(ET.tostring(root, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<collection>
    <genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back 2 the Future">
               <format multiple="False">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    </genre>

    <genre category="Thriller">
        <decade years="1970s">
            <movie favorite="False" title="ALIEN">
                <format multiple="Yes">DVD</format>
                <year>1979</year>
                <rating>R</rating>
                <description>"""""""""</description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="True" title="Ferris Bueller's Day Off">
                <format multiple="No">DVD</format>
                <year>1986</year>
                <rating>PG13</rating>
                <description>Funny movie about a funny guy</description>
            </movie>
            <movie favorite="FALSE" title="American Psycho">
                <format multiple="No">blue-ray</format>
                <year>2000</year>
                <rating>Unrated</rating>
                <description>psychopathic Bateman</description>
            </movie>
        </decade>
    </genre>

    <genre category="Comedy">
        <decade years="1960s">
            <movie favorite="False" title="Batman: The Movie">
                <format multiple="Yes">DVD,VHS</format>
                <year>1966</year>
                <rating>PG</rating>
                <description>What a joke!</description>
            </movie>
        </decade>
        <decade years="2010s">
            <movie favorite="True" title="Easy A">
                <format multiple="No">DVD</format>
                <year>2010</year>
                <rating>PG--13</rating>
                <description>Emma Stone = Hester Prynne</description>
            </movie>
            <movie favorite="True" title="Dinner for SCHMUCKS">
                <format multiple="Yes">DVD,digital,Netflix</format>
                <year>2011</year>
                <rating>Unrated</rating>
                <description>Tim (Rudd) is a rising executive
                 who “succeeds” in finding the perfect guest, 
                 IRS employee Barry (Carell), for his boss’ monthly event, 
                 a so-called “dinner for idiots,” which offers certain 
                 advantages to the exec who shows up with the biggest buffoon.
                 </description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="False" title="Ghostbusters">
                <format multiple="No">Online,VHS</format>
                <year>1984</year>
                <rating>PG</rating>
                <description>Who ya gonna call?</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Robin Hood: Prince of Thieves">
                <format multiple="No">Blu_Ray</format>
                <year>1991</year>
                <rating>Unknown</rating>
                <description>Robin Hood slaying</description>
            </movie>
        </decade>
    </genre>
</collection>

आप iter() फ़ंक्शन के उपयोग का विस्तार करके रुचि के विशेष एलिमेंट्स को खोजने में मदद ले सकते हैं। root.iter() रूट के अंतर्गत उन सभी सबएलीमेंट्स की सूची देगा जो निर्दिष्ट एलिमेंट से मेल खाते हैं। यहाँ, आप ट्री में movie एलिमेंट के सभी attributes की सूची बनाएँगे:

for movie in root.iter('movie'):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

आप पहले से ही देख सकते हैं कि movies को अलग-अलग तरीकों से दर्ज किया गया है। फिलहाल इसकी चिंता न करें। आपको इस ट्यूटोरियल में आगे जाकर त्रुटियों में से एक को ठीक करने का मौका मिलेगा।

XPath अभिव्यक्तियाँ

कई बार एलिमेंट्स के attributes नहीं होते, केवल टेक्स्ट सामग्री होती है। attribute .text का उपयोग करके, आप इस सामग्री को प्रिंट कर सकते हैं।

अब, फिल्मों के सभी विवरण प्रिंट करें।

for description in root.iter('description'):
    print(description.text)
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'

None provided.
Marty McFly
Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.
NA.
WhAtEvER I Want!!!?!
"""""""""
Funny movie about a funny guy
psychopathic Bateman
What a joke!
Emma Stone = Hester Prynne
Tim (Rudd) is a rising executive
                 who “succeeds” in finding the perfect guest, 
                 IRS employee Barry (Carell), for his boss’ monthly event, 
                 a so-called “dinner for idiots,” which offers certain 
                 advantages to the exec who shows up with the biggest buffoon.

Who ya gonna call?
Robin Hood slaying

XML को प्रिंट करना सहायक है, लेकिन XPath एक क्वेरी भाषा है जिसका उपयोग किसी XML में तेज़ी और आसानी से खोज करने के लिए किया जाता है। XPath का अर्थ है XML Path Language और, जैसा कि नाम से पता चलता है, यह किसी XML दस्तावेज़ में नोड्स की पहचान और नेविगेट करने के लिए "path-जैसी" सिंटैक्स का उपयोग करता है।

XMLs को स्कैन और पॉप्युलेट करने के लिए XPath को समझना अत्यंत महत्वपूर्ण है। ElementTree में .findall() फ़ंक्शन होता है जो संदर्भित एलिमेंट के तात्कालिक बच्चों को ट्रैवर्स करेगा। आप अधिक उपयोगी खोजों को निर्दिष्ट करने के लिए XPath अभिव्यक्तियों का उपयोग कर सकते हैं।

यहाँ, आप 1992 में रिलीज़ हुई फिल्मों को ट्री में खोजेंगे:

for movie in root.findall("./genre/decade/movie/[year='1992']"):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}

.findall() फ़ंक्शन हमेशा निर्दिष्ट एलिमेंट से शुरू होता है। इस प्रकार का फ़ंक्शन "find and replace" के लिए बेहद शक्तिशाली है। आप attributes पर भी खोज कर सकते हैं!

अब, केवल वे फिल्में प्रिंट करें जो कई फ़ॉर्मैट्स में उपलब्ध हैं (एक attribute)।

for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):
    print(movie.attrib)
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}

सोचें कि इस मामले में प्रिंट स्टेटमेंट multiple के "Yes" मान क्यों लौटाता है। देखें कि "for" लूप कैसे परिभाषित किया गया है। क्या आप इस लूप को फिर से लिख सकते हैं ताकि यह मूवी के शीर्षक प्रिंट करे? नीचे प्रयास करें:

टिप: वर्तमान एलिमेंट के पैरेंट एलिमेंट को लौटाने के लिए XPath के अंदर '...' का उपयोग करें।

for movie in root.findall("./genre/decade/movie/format[@multiple='Yes']..."):
    print(movie.attrib)
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}

XML संशोधित करना

पहले, मूवी शीर्षक बिल्कुल गड़बड़ थे। अब उन्हें फिर से प्रिंट करें:

for movie in root.iter('movie'):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

Back 2 the Future में '2' को ठीक करें। यह एक find-and-replace समस्या होनी चाहिए। 'Back 2 the Future' शीर्षक को खोजने और उसे एक वेरिएबल के रूप में सहेजने के लिए कोड लिखें:

b2tf = root.find("./genre/decade/movie[@title='Back 2 the Future']")
print(b2tf)
<Element 'movie' at 0x10ce00ef8>

ध्यान दें कि .find() मेथड का उपयोग करने से ट्री का एक एलिमेंट रिटर्न होता है। अधिकतर समय, किसी एलिमेंट के भीतर की सामग्री को संपादित करना अधिक उपयोगी होता है।

Back 2 the Future एलिमेंट वेरिएबल के title attribute को संशोधित करें ताकि वह "Back to the Future" पढ़े। फिर, अपना बदलाव देखने के लिए अपने वेरिएबल के attributes प्रिंट करें। आप किसी एलिमेंट के attribute को एक्सेस कर, फिर उसे नया मान असाइन करके यह आसानी से कर सकते हैं:

b2tf.attrib["title"] = "Back to the Future"
print(b2tf.attrib)
{'favorite': 'False', 'title': 'Back to the Future'}

अपने बदलावों को वापस XML में लिखें ताकि वे दस्तावेज़ में स्थायी रूप से ठीक हो जाएँ। सुनिश्चित करने के लिए कि बदलाव काम कर गए हैं, अपने मूवी attributes फिर से प्रिंट करें। ऐसा करने के लिए .write() मेथड का उपयोग करें:

tree.write("movies.xml")

tree = ET.parse('movies.xml')
root = tree.getroot()

for movie in root.iter('movie'):
    print(movie.attrib)
{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back to the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

Attributes ठीक करना

multiple attribute कुछ जगहों पर गलत है। मूवी कितने फ़ॉर्मैट्स में आती है, इसके आधार पर डिज़ाइनेटर को ठीक करने के लिए ElementTree का उपयोग करें। पहले, किस हिस्से को ठीक करना है यह देखने के लिए format attribute और टेक्स्ट प्रिंट करें।

for form in root.findall("./genre/decade/movie/format"):
    print(form.attrib, form.text)
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'False'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'Yes'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'No'} Online,VHS
{'multiple': 'No'} Blu_Ray

इस टैग पर कुछ काम करने की ज़रूरत है।

आप कॉमा ढूँढ़ने के लिए regex का उपयोग कर सकते हैं - इससे पता चलेगा कि multiple attribute "Yes" होना चाहिए या "No"। attributes जोड़ना और संशोधित करना .set() मेथड से आसानी से किया जा सकता है।

नोट: re Python के लिए मानक regex इंटरप्रेटर है। यदि आप रेगुलर एक्सप्रेशंस के बारे में अधिक जानना चाहते हैं, तो यह ट्यूटोरियल देखें।

import re

for form in root.findall("./genre/decade/movie/format"):
    # Search for the commas in the format text
    match = re.search(',',form.text)
    if match:
        form.set('multiple','Yes')
    else:
        form.set('multiple','No')

# Write out the tree to the file again
tree.write("movies.xml")

tree = ET.parse('movies.xml')
root = tree.getroot()

for form in root.findall("./genre/decade/movie/format"):
    print(form.attrib, form.text)
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'No'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'No'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'Yes'} Online,VHS
{'multiple': 'No'} Blu_Ray

एलिमेंट्स को स्थानांतरित करना

कुछ डेटा गलत दशक में रखा गया है। XML और ElementTree के बारे में आपने जो सीखा है, उसका उपयोग करके दशक से संबंधित डेटा त्रुटियों को ढूँढ़ें और ठीक करें।

दस्तावेज़ भर में decade टैग्स और year टैग्स दोनों को प्रिंट करना उपयोगी होगा।

for decade in root.findall("./genre/decade"):
    print(decade.attrib)
    for year in decade.findall("./movie/year"):
        print(year.text, '\n')
{'years': '1980s'}
1981 

1984 

1985 

{'years': '1990s'}
2000 

1992 

1992 

{'years': '1970s'}
1979 

{'years': '1980s'}
1986 

2000 

{'years': '1960s'}
1966 

{'years': '2010s'}
2010 

2011 

{'years': '1980s'}
1984 

{'years': '1990s'}
1991 

दो साल जो गलत दशक में हैं, वे 2000s की फ़िल्में हैं। XPath अभिव्यक्ति का उपयोग करके पता लगाएँ कि वे फ़िल्में कौन-सी हैं।

for movie in root.findall("./genre/decade/movie/[year='2000']"):
    print(movie.attrib)
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'FALSE', 'title': 'American Psycho'}

आपको Action शैली में 2000s का नया decade टैग जोड़ना होगा ताकि X-Men डेटा को स्थानांतरित किया जा सके। .SubElement() मेथड का उपयोग करके आप इस टैग को XML के अंत में जोड़ सकते हैं।

action = root.find("./genre[@category='Action']")
new_dec = ET.SubElement(action, 'decade')
new_dec.attrib["years"] = '2000s'

print(ET.tostring(action, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back to the Future">
               <format multiple="No">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    <decade years="2000s" /></genre>

अब X-Men मूवी को 2000s में जोड़ें और उसे 1990s से हटाएँ, क्रमशः .append() और .remove() का उपयोग करके।

xmen = root.find("./genre/decade/movie[@title='X-Men']")
dec2000s = root.find("./genre[@category='Action']/decade[@years='2000s']")
dec2000s.append(xmen)
dec1990s = root.find("./genre[@category='Action']/decade[@years='1990s']")
dec1990s.remove(xmen)

print(ET.tostring(action, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back to the Future">
               <format multiple="No">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    <decade years="2000s"><movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            </decade></genre>

XML दस्तावेज़ बनाना

अच्छा, तो आप मूल रूप से पूरी मूवी को एक नए दशक में स्थानांतरित करने में सक्षम रहे। अपने बदलावों को XML में सहेजें।

tree.write("movies.xml")

tree = ET.parse('movies.xml')
root = tree.getroot()

print(ET.tostring(root, encoding='utf8').decode('utf8'))
<?xml version='1.0' encoding='utf8'?>
<collection>
    <genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back to the Future">
               <format multiple="No">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    <decade years="2000s"><movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            </decade></genre>

    <genre category="Thriller">
        <decade years="1970s">
            <movie favorite="False" title="ALIEN">
                <format multiple="No">DVD</format>
                <year>1979</year>
                <rating>R</rating>
                <description>"""""""""</description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="True" title="Ferris Bueller's Day Off">
                <format multiple="No">DVD</format>
                <year>1986</year>
                <rating>PG13</rating>
                <description>Funny movie about a funny guy</description>
            </movie>
            <movie favorite="FALSE" title="American Psycho">
                <format multiple="No">blue-ray</format>
                <year>2000</year>
                <rating>Unrated</rating>
                <description>psychopathic Bateman</description>
            </movie>
        </decade>
    </genre>

    <genre category="Comedy">
        <decade years="1960s">
            <movie favorite="False" title="Batman: The Movie">
                <format multiple="Yes">DVD,VHS</format>
                <year>1966</year>
                <rating>PG</rating>
                <description>What a joke!</description>
            </movie>
        </decade>
        <decade years="2010s">
            <movie favorite="True" title="Easy A">
                <format multiple="No">DVD</format>
                <year>2010</year>
                <rating>PG--13</rating>
                <description>Emma Stone = Hester Prynne</description>
            </movie>
            <movie favorite="True" title="Dinner for SCHMUCKS">
                <format multiple="Yes">DVD,digital,Netflix</format>
                <year>2011</year>
                <rating>Unrated</rating>
                <description>Tim (Rudd) is a rising executive
                 who “succeeds” in finding the perfect guest, 
                 IRS employee Barry (Carell), for his boss’ monthly event, 
                 a so-called “dinner for idiots,” which offers certain 
                 advantages to the exec who shows up with the biggest buffoon.
                 </description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="False" title="Ghostbusters">
                <format multiple="Yes">Online,VHS</format>
                <year>1984</year>
                <rating>PG</rating>
                <description>Who ya gonna call?</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Robin Hood: Prince of Thieves">
                <format multiple="No">Blu_Ray</format>
                <year>1991</year>
                <rating>Unknown</rating>
                <description>Robin Hood slaying</description>
            </movie>
        </decade>
    </genre>
</collection>

ElementTree में नया क्या है?

नए Python संस्करणों में ElementTree लाइब्रेरी की नई सुविधाओं और सुधारों का यह एक अवलोकन है:

1. XPath 1.0 समर्थन (Python 3.8): Python 3.8 से शुरू होकर, ElementTree में find() और findall() मेथड्स के साथ पूरा XPath 1.0 समर्थन शामिल है, जो अधिक समृद्ध और जटिल XML क्वेरीज़ को सक्षम करता है। उदाहरण:

# Finding all movies with a specific attribute using XPath
for movie in root.findall(".//movie[@favorite='True']"):
    print(movie.attrib)

2. नेमस्पेसेज़ में सुधार (Python 3.8+): XML namespaces के लिए उन्नत समर्थन, जो प्रीफ़िक्स्ड या डिफ़ॉल्ट नेमस्पेस का उपयोग करने वाली XML फ़ाइलों के साथ इंटरैक्शन को और अधिक सरल बनाता है। उदाहरण:

# Register a namespace and find elements using it
ET.register_namespace('', 'http://example.com/namespace')
movies = root.findall(".//{http://example.com/namespace}movie")

3. पार्सर एन्हांसमेंट्स (Python 3.9): बेहतर पार्सिंग एरर संदेश, जिससे खराब-फ़ॉर्म्ड XML फ़ाइलों को डीबग करना आसान हो जाता है।

4. नया indent() फ़ंक्शन (Python 3.9): xml.etree.ElementTree.indent() फ़ंक्शन जो XML दस्तावेज़ों को उनके एलिमेंट्स को इंडेंट करके सुगठित रूप में प्रिंट करता है, जोड़ा गया। उदाहरण:

ET.indent(root, space="  ", level=0)
ET.dump(root)

5. iterparse के साथ कुशल पार्सिंग (Python 3.10): मेमोरी दक्षता के लिए अनुकूलित, विशेष रूप से बड़े XML फ़ाइलों के साथ काम करते समय उपयोगी।

6. विस्तारित डॉक्यूमेंटेशन (निरंतर अपडेट): Python का ElementTree डॉक्यूमेंटेशन अब अधिक व्यापक है, जिसमें सर्वोत्तम प्रथाएँ और उन्नत उपयोग के मामले शामिल हैं।

ElementTree में डिप्रिकेटेड फीचर्स और विकल्प

1. Python 3.8+ में xml_declaration के साथ write(): write() मेथड का xml_declaration पैरामीटर तब डिप्रिकेटेड है जब एन्कोडिंग 'unicode' पर सेट हो।

  • विकल्प: xml_declaration का उपयोग केवल तब करें जब एन्कोडिंग को स्पष्ट रूप से 'unicode' के अलावा कुछ और परिभाषित किया गया हो।
tree.write("output.xml", encoding="utf-8", xml_declaration=True)

2. HTML पार्सर: यद्यपि आधिकारिक तौर पर डिप्रिकेटेड नहीं है, लेकिन HTML पार्सिंग के लिए ElementTree का उपयोग करने की अनुशंसा नहीं की जाती क्योंकि यह non-well-formed HTML को संभालने में सीमित है।

  • विकल्प: HTML पार्सिंग के लिए विशेष रूप से डिज़ाइन की गई लाइब्रेरीज़ का उपयोग करें, जैसे bs4 पैकेज की BeautifulSoup।
from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, 'html.parser')

3. नेमस्पेस हैंडलिंग वर्कअराउंड्स: नेमस्पेस सपोर्ट के मजबूत होने के साथ पुराने तरीके (जैसे namespace URI को एलिमेंट टैग्स के साथ जोड़ना) अब कम सुझाए जाते हैं।

  • विकल्प: बिल्ट-इन नेमस्पेस-अवेयर मेथड्स और फ़ंक्शंस का उपयोग करें।
ET.register_namespace('', 'http://example.com/namespace') movies = root.findall(".//{http://example.com/namespace}movie")

4. मैनुअल प्रिटी-प्रिंटिंग: इंडेंटिंग और फ़ॉर्मैटिंग के मैनुअल तरीकों को नए indent() फ़ंक्शन (Python 3.9) ने अप्रचलित बना दिया है।

  • विकल्प: स्वचालित XML फ़ॉर्मैटिंग के लिए ET.indent() का उपयोग करें।
ET.indent(root, space=" ")

5. _ElementInterface का डायरेक्ट उपयोग: _ElementInterface जैसी इंटरनल क्लासेस डायरेक्ट उपयोग के लिए अभिप्रेत नहीं हैं और भविष्य के संस्करणों में टूट सकती हैं।

  • विकल्प: हमेशा ElementTree लाइब्रेरी के डॉक्यूमेंटेड पब्लिक API के साथ ही इंटरैक्ट करें।

निष्कर्ष

XMLs और ElementTree का उपयोग करने के बारे में कुछ प्रमुख बातें याद रखने योग्य हैं।

टैग्स ट्री संरचना बनाते हैं और यह निर्धारित करते हैं कि वहाँ किन मानों को विभाजित किया जाना चाहिए। स्मार्ट स्ट्रक्चरिंग का उपयोग करके XML को पढ़ना और लिखना आसान हो सकता है। पैरेंट और चिल्ड्रन संबंध दिखाने के लिए टैग्स को हमेशा ओपनिंग और क्लोज़िंग ब्रैकेट्स की आवश्यकता होती है।

Attributes और अधिक बताते हैं कि किसी टैग को कैसे वैलिडेट करना है या boolean डिज़ाइनेशंस की अनुमति देते हैं। attributes आमतौर पर बहुत विशिष्ट मान लेते हैं ताकि XML पार्सर (और उपयोगकर्ता) attributes का उपयोग करके टैग मानों की जाँच कर सकें।

ElementTree एक महत्वपूर्ण Python लाइब्रेरी है जो आपको किसी XML दस्तावेज़ को पार्स और नेविगेट करने की अनुमति देती है। ElementTree का उपयोग करने से XML दस्तावेज़ एक ट्री संरचना में टूट जाता है जिसके साथ काम करना आसान होता है। जब संदेह हो, तो प्रिंट कर दें (print(ET.tostring(root, encoding='utf8').decode('utf8'))) - पूरे XML दस्तावेज़ को एक साथ देखने के लिए इस सहायक प्रिंट स्टेटमेंट का उपयोग करें। यह तब जाँचने में मदद करता है जब आप किसी XML में संपादन, जोड़ या हटाना कर रहे हों।

अब, आप XML को समझने और पार्सिंग शुरू करने के लिए सक्षम हैं!

Steph Howson

लेखक

Steph Howson

FAQs

डेटा साइंस में XML के कुछ सामान्य उपयोग क्या हैं?

डेटा साइंस में XML का उपयोग अक्सर सिस्टम्स के बीच डेटा इंटरचेंज, वेब स्क्रैपिंग, कॉन्फ़िगरेशन फ़ाइलें, और जटिल, पदानुक्रमित संरचना वाले डेटा को संभालने के लिए किया जाता है। यह विशेष रूप से तब उपयोगी है जब आप ऐसे APIs के साथ काम कर रहे हों जो XML डेटा लौटाते हैं।

क्या ElementTree बड़ी XML फ़ाइलों को कुशलतापूर्वक संभाल सकता है?

ElementTree मध्यम आकार की XML फ़ाइलों को संभालने के लिए उपयुक्त है, लेकिन बहुत बड़ी फ़ाइलों के लिए, आप lxml या xml.sax जैसी लाइब्रेरीज़ पर विचार कर सकते हैं जो अधिक मेमोरी-कुशल हैं और बड़ी फ़ाइलों की स्ट्रीमिंग संभाल सकती हैं।

ElementTree की अन्य XML पार्सिंग लाइब्रेरीज़ जैसे lxml या minidom से तुलना कैसे होती है?

ElementTree Python की मानक लाइब्रेरी का हिस्सा है और बुनियादी XML पार्सिंग कार्यों के लिए उपयोग में आसान है। lxml अधिक शक्तिशाली और तेज़ है, जो XPath 2.0 सपोर्ट जैसी अतिरिक्त सुविधाएँ प्रदान करता है। minidom, एक अन्य मानक लाइब्रेरी, Document Object Model (DOM) पर आधारित है और बड़े दस्तावेज़ों के लिए कम कुशल है।

XPath अभिव्यक्तियाँ क्या हैं और XML पार्सिंग में वे कैसे उपयोगी हैं?

XPath अभिव्यक्तियाँ XML दस्तावेज़ से नोड्स चुनने के लिए क्वेरी भाषाएँ हैं। वे XML दस्तावेज़ों में एलिमेंट्स और attributes के माध्यम से नेविगेट करने में उपयोगी हैं, जिससे सटीक डेटा पुनर्प्राप्ति और हेरफेर संभव होता है।

ElementTree से पार्स करने से पहले मैं किसी XML दस्तावेज़ को कैसे वैलिडेट कर सकता/सकती हूँ?

XML दस्तावेज़ों को XML Schema Definition (XSD) या Document Type Definition (DTD) का उपयोग करके वैलिडेट किया जा सकता है। Python लाइब्रेरीज़ जैसे lxml इन मानकों के विरुद्ध वैलिडेशन के लिए बिल्ट-इन सपोर्ट प्रदान करती हैं।

ElementTree का उपयोग करके XML डेटा संशोधित करने के लिए कुछ सर्वोत्तम प्रथाएँ क्या हैं?

सर्वोत्तम प्रथाओं में आकस्मिक डेटा हानि से बचने के लिए XML डेटा की एक प्रति पर काम करना, सटीक नेविगेशन के लिए XPath अभिव्यक्तियों का उपयोग करना, और यह सुनिश्चित करना शामिल है कि सभी परिवर्तन XML दस्तावेज़ की well-formedness बनाए रखें।

क्या ElementTree का उपयोग XML डेटा को JSON में बदलने के लिए किया जा सकता है?

हालाँकि ElementTree सीधे XML-से-JSON रूपांतरण प्रदान नहीं करता, आप ElementTree का उपयोग करके XML डेटा को Python डिक्शनरी में पार्स कर सकते हैं और फिर Python के json मॉड्यूल का उपयोग करके डिक्शनरी को JSON में बदल सकते हैं।

ElementTree के साथ XML namespaces को कैसे संभालते हैं?

ElementTree XML namespaces को टैग नामों में {namespace} प्रीफ़िक्स का उपयोग करके संभाल सकता है। आप आसान हैंडलिंग के लिए ET.register_namespace() के साथ नेमस्पेसेज़ रजिस्टर भी कर सकते हैं।

यदि मुझे ElementTree में XML parsing एरर मिले तो मुझे क्या करना चाहिए?

सामान्य समस्याएँ जैसे malformed XML, असमर्थित एन्कोडिंग, या गलत फ़ाइल पथ की जाँच करें। parsing त्रुटियों का सुचारू रूप से निदान और प्रबंधन करने के लिए Python के एरर हैंडलिंग (try-except ब्लॉक्स) का उपयोग करें।

क्या ElementTree का उपयोग करके किसी XML दस्तावेज़ को प्रिटी-प्रिंट करना संभव है?

ElementTree सीधे प्रिटी-प्रिंटिंग प्रदान नहीं करता, लेकिन आप xml.dom.minidom का उपयोग करके XML स्ट्रिंग को पार्स कर सकते हैं और फिर उसकी toprettyxml() मेथड का उपयोग करके XML को पठनीयता के लिए फ़ॉर्मैट कर सकते हैं।

विषय