python मैं पायथन में एक्सएमएल का विश्लेषण कैसे करूं?




xml (10)

मेरे पास डेटाबेस में कई पंक्तियां हैं जिनमें xml है और मैं एक पायथन स्क्रिप्ट लिखने की कोशिश कर रहा हूं जो उन पंक्तियों के माध्यम से जायेगा और गिनती होगी कि किसी विशेष नोड विशेषता के कितने उदाहरण दिखाए जाते हैं। उदाहरण के लिए, मेरा पेड़ इस तरह दिखता है:

<foo>
   <bar>
      <type foobar="1"/>
      <type foobar="2"/>
   </bar>
</foo>

मैं पायथन का उपयोग कर एक्सएमएल में गुण 1 और 2 तक कैसे पहुंच सकता हूं?


cElementTree का उपयोग करके यहां एक बहुत ही सरल लेकिन प्रभावी कोड है।

try:
    import cElementTree as ET
except ImportError:
  try:
    # Python 2.5 need to import a different module
    import xml.etree.cElementTree as ET
  except ImportError:
    exit_err("Failed to import cElementTree from any known place")      

def find_in_tree(tree, node):
    found = tree.find(node)
    if found == None:
        print "No %s in file" % node
        found = []
    return found  

# Parse a xml file (specify the path)
def_file = "xml_file_name.xml"
try:
    dom = ET.parse(open(def_file, "r"))
    root = dom.getroot()
except:
    exit_err("Unable to open and parse input definition file: " + def_file)

# Parse to find the child nodes list of node 'myNode'
fwdefs = find_in_tree(root,"myNode")

स्रोत:

http://www.snip2code.com/Snippet/991/python-xml-parse?fromPage=1


वहां कई विकल्प हैं। अगर गति और स्मृति उपयोग एक मुद्दा है तो cElementTree उत्कृष्ट दिखता है। readlines का उपयोग कर फ़ाइल में पढ़ने की तुलना में यह बहुत कम ओवरहेड है।

प्रासंगिक मेट्रिक्स नीचे दी गई तालिका में पाया जा सकता है, cElementTree वेबसाइट से कॉपी किया गया है:

library                         time    space
xml.dom.minidom (Python 2.1)    6.3 s   80000K
gnosis.objectify                2.0 s   22000k
xml.dom.minidom (Python 2.4)    1.4 s   53000k
ElementTree 1.2                 1.6 s   14500k  
ElementTree 1.2.4/1.3           1.1 s   14500k  
cDomlette (C extension)         0.540 s 20500k
PyRXPU (C extension)            0.175 s 10850k
libxml2 (C extension)           0.098 s 16000k
readlines (read as utf-8)       0.093 s 8850k
cElementTree (C extension)  --> 0.047 s 4900K <--
readlines (read as ascii)       0.032 s 5050k   

जैसा कि @jfs द्वारा इंगित किया गया है, cElementTree पायथन के साथ बंडल आता है:

  • पायथन 2: from xml.etree import cElementTree as ElementTree
  • पायथन 3: from xml.etree import ElementTree (त्वरित सी संस्करण स्वचालित रूप से उपयोग किया जाता है)।

minidom सबसे तेज़ और सुंदर सीधे आगे है:

एक्सएमएल:

<data>
    <items>
        <item name="item1"></item>
        <item name="item2"></item>
        <item name="item3"></item>
        <item name="item4"></item>
    </items>
</data>

अजगर:

from xml.dom import minidom
xmldoc = minidom.parse('items.xml')
itemlist = xmldoc.getElementsByTagName('item')
print(len(itemlist))
print(itemlist[0].attributes['name'].value)
for s in itemlist:
    print(s.attributes['name'].value)

आउटपुट

4
item1
item1
item2
item3
item4

बस एक और संभावना जोड़ने के लिए, आप untangle का उपयोग कर सकते हैं, क्योंकि यह एक साधारण xml-to-python-object लाइब्रेरी है। यहां आपके पास एक उदाहरण है:

स्थापना

pip install untangle

प्रयोग

आपकी एक्सएमएल फ़ाइल (थोड़ा सा बदल गया):

<foo>
   <bar name="bar_name">
      <type foobar="1"/>
   </bar>
</foo>

असंगतताओं के साथ विशेषताओं तक पहुंच:

import untangle

obj = untangle.parse('/path_to_xml_file/file.xml')

print obj.foo.bar['name']
print obj.foo.bar.type['foobar']

आउटपुट होगा:

bar_name
1

अछूत के बारे में अधिक जानकारी here मिल सकती here
इसके अलावा (यदि आप उत्सुक हैं), तो आप here एक्सएमएल और पायथन के साथ काम करने के लिए टूल की एक सूची पा सकते हैं (आप यह भी देखेंगे कि पिछले उत्तरों द्वारा सबसे आम लोगों का उल्लेख किया गया था)।


import xml.etree.ElementTree as ET
data = '''<foo>
           <bar>
               <type foobar="1"/>
               <type foobar="2"/>
          </bar>
       </foo>'''
tree = ET.fromstring(data)
lst = tree.findall('bar/type')
for item in lst:
    print item.get('foobar')

यह foobar विशेषता के मूल्य मुद्रित करेगा।


मुझे पाइथन xml.dom और xml.dom.minidom काफी आसान लगता है। ध्यान रखें कि डीओएम बड़ी मात्रा में एक्सएमएल के लिए अच्छा नहीं है, लेकिन यदि आपका इनपुट काफी छोटा है तो यह ठीक काम करेगा।


lxml.objectify वास्तव में सरल है।

अपना नमूना पाठ लेना:

from lxml import objectify
from collections import defaultdict

count = defaultdict(int)

root = objectify.fromstring(text)

for item in root.bar.type:
    count[item.attrib.get("foobar")] += 1

print dict(count)

आउटपुट:

{'1': 1, '2': 1}

आप BeautifulSoup उपयोग कर सकते हैं

from bs4 import BeautifulSoup

x="""<foo>
   <bar>
      <type foobar="1"/>
      <type foobar="2"/>
   </bar>
</foo>"""

y=BeautifulSoup(x)
>>> y.foo.bar.type["foobar"]
u'1'

>>> y.foo.bar.findAll("type")
[<type foobar="1"></type>, <type foobar="2"></type>]

>>> y.foo.bar.findAll("type")[0]["foobar"]
u'1'
>>> y.foo.bar.findAll("type")[1]["foobar"]
u'2'

मैं ElementTree सुझाव देता हूं। एक ही एपीआई के अन्य संगत कार्यान्वयन हैं, जैसे कि cElementTree , और पायथन मानक लाइब्रेरी में cElementTree ; लेकिन, इस संदर्भ में, वे जो मुख्य रूप से जोड़ते हैं वह और भी गति है - प्रोग्रामिंग भाग की आसानी एपीआई पर निर्भर करती है, जिसे ElementTree परिभाषित करता है।

एक्सएमएल से एलिमेंट इंस्टेंस e बनाने के बाद, उदाहरण के लिए XML फ़ंक्शन के साथ, या किसी फ़ाइल के साथ फ़ाइल को पार्स करके

import xml.etree.ElementTree
e = xml.etree.ElementTree.parse('thefile.xml').getroot()

या ElementTree पर दिखाए गए कई अन्य तरीकों में से कोई भी, आप बस कुछ ऐसा करते हैं:

for atype in e.findall('type'):
    print(atype.get('foobar'))

और इसी तरह, आमतौर पर बहुत सरल, कोड पैटर्न।


मैं declxml सुझाव दे सकता declxml

पूर्ण प्रकटीकरण: मैंने इस पुस्तकालय को लिखा क्योंकि मैं एलीमेंट ट्री के साथ अनिवार्य पार्सिंग / क्रमबद्धता कोड के दर्जनों लाइनों को लिखने के बिना एक्सएमएल और पायथन डेटा संरचनाओं के बीच परिवर्तित करने का एक तरीका ढूंढ रहा था।

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

पायथन डेटा संरचनाओं में पार्सिंग सरल है:

import declxml as xml

xml_string = """
<foo>
   <bar>
      <type foobar="1"/>
      <type foobar="2"/>
   </bar>
</foo>
"""

processor = xml.dictionary('foo', [
    xml.dictionary('bar', [
        xml.array(xml.integer('type', attribute='foobar'))
    ])
])

xml.parse_from_string(processor, xml_string)

जो उत्पादन का उत्पादन करता है:

{'bar': {'foobar': [1, 2]}}

आप एक्सएमएल में डेटा क्रमबद्ध करने के लिए एक ही प्रोसेसर का भी उपयोग कर सकते हैं

data = {'bar': {
    'foobar': [7, 3, 21, 16, 11]
}}

xml.serialize_to_string(processor, data, indent='    ')

जो निम्नलिखित आउटपुट उत्पन्न करता है

<?xml version="1.0" ?>
<foo>
    <bar>
        <type foobar="7"/>
        <type foobar="3"/>
        <type foobar="21"/>
        <type foobar="16"/>
        <type foobar="11"/>
    </bar>
</foo>

यदि आप शब्दकोशों के बजाय ऑब्जेक्ट्स के साथ काम करना चाहते हैं, तो आप प्रोसेसर को ऑब्जेक्ट्स से डेटा को बदलने के लिए भी परिभाषित कर सकते हैं।

import declxml as xml

class Bar:

    def __init__(self):
        self.foobars = []

    def __repr__(self):
        return 'Bar(foobars={})'.format(self.foobars)


xml_string = """
<foo>
   <bar>
      <type foobar="1"/>
      <type foobar="2"/>
   </bar>
</foo>
"""

processor = xml.dictionary('foo', [
    xml.user_object('bar', Bar, [
        xml.array(xml.integer('type', attribute='foobar'), alias='foobars')
    ])
])

xml.parse_from_string(processor, xml_string)

जो निम्नलिखित आउटपुट उत्पन्न करता है

{'bar': Bar(foobars=[1, 2])}




xml