Рубрики
Без рубрики

Python: разбор XML с миниинком

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Если вы давний читатель, вы можете вспомнить, что я начал программировать Python в 2006 году. В течение года или около того, мой работодатель решил отойти от Microsoft Exchange на клиент с открытым исходным кодом Zimbra. Zimbra – это все в порядке, но это было пропущено хорошим способом предупредить пользователя к тому, что у них была встреча, поэтому мне пришлось создать способ запросить Zimbra для этой информации и показать диалог. Что все это Mumbo Jumbo связано с XML, хотя? Ну, я думал, что использование XML было бы отличным способом отслеживать, какие назначения были добавлены, удалены, обернутые или что-то еще. Оказалось, что я ошибался, но это не точка этой истории.

В этой статье мы собираемся посмотреть на мой первый набор в разбор XML с Python. Если вы делаете небольшое исследование этой темы, вы скоро обнаружите, что Python имеет анализатор XML, встроенный на язык в его XML модуль. Я закончил использовать Минизм Подкомпонент этого модуля … хотя бы сначала. В конце концов я переключился на LXML, который использует ElementTree, но это за пределами объема этой статьи. Давайте посмотрим на некоторое уродливое XML, которое я придумал:



    
        1181251680        
        040000008200E000
        1181572063
        
        
        1800
        Bring pizza home
    

Теперь мы знаем, что мне нужно было разбирать. Давайте посмотрим на типичный способ разбить что-то вроде этого, используя миниин в Python.

import xml.dom.minidom
import urllib2

class ApptParser(object):

    def __init__(self, url, flag='url'):
        self.list = []
        self.appt_list = []        
        self.flag = flag
        self.rem_value = 0
        xml = self.getXml(url) 
        print "xml"
        print xml
        self.handleXml(xml)
        
    def getXml(self, url):
        try:
            print url
            f = urllib2.urlopen(url)
        except:
            f = url
        #print f
        doc = xml.dom.minidom.parse(f)
        node = doc.documentElement        
        if node.nodeType == xml.dom.Node.ELEMENT_NODE:
            print 'Element name: %s' % node.nodeName
            for (name, value) in node.attributes.items():
                #print '    Attr -- Name: %s  Value: %s' % (name, value)
                if name == 'reminder':
                    self.rem_value = value                    
    
        return node

    def handleXml(self, xml):
        rem = xml.getElementsByTagName('zAppointments')        
        appointments = xml.getElementsByTagName("appointment")
        self.handleAppts(appointments)

    def getElement(self, element):
        return self.getText(element.childNodes)

    def handleAppts(self, appts):
        for appt in appts:
            self.handleAppt(appt)
            self.list = []

    def handleAppt(self, appt):
        begin     = self.getElement(appt.getElementsByTagName("begin")[0])
        duration  = self.getElement(appt.getElementsByTagName("duration")[0])
        subject   = self.getElement(appt.getElementsByTagName("subject")[0])
        location  = self.getElement(appt.getElementsByTagName("location")[0])
        uid       = self.getElement(appt.getElementsByTagName("uid")[0])
        
        self.list.append(begin)
        self.list.append(duration)
        self.list.append(subject)
        self.list.append(location)
        self.list.append(uid)
        if self.flag == 'file':
            
            try:
                state     = self.getElement(appt.getElementsByTagName("state")[0])
                self.list.append(state)
                alarm     = self.getElement(appt.getElementsByTagName("alarmTime")[0])
                self.list.append(alarm)
            except Exception, e:
                print e
            
        self.appt_list.append(self.list)        

    def getText(self, nodelist):
        rc = ""
        for node in nodelist:
            if node.nodeType == node.TEXT_NODE:
                rc = rc + node.data
        return rc

Если я правильно вспомню, этот код был основан на примере из документации Python (или, возможно, глава в нырясе в Python). Мне все еще не нравится этот код. URL Параметр, который вы видите в APPTPARSER Класс может быть либо URL или файлом. У меня был корм XML от Зимбры, который я бы периодически проверял для изменений и сравниваю его с последней копией этого XML, которую я скачал. Если было что-то новое, я бы добавил изменения в загруженную копию. Во всяком случае, давайте распадаем этот код немного.

В getxml Мы используем обработчик исключения, чтобы попытаться открыть URL. Если это произойдет, чтобы поднять ошибку, чем мы предполагаем, что URL на самом деле является файлом. Далее мы используем Minikom’s Разбор Метод для анализа XML. Затем мы вытащим узел из XML. Мы проигнорируем условную, как не важно для этой дискуссии (это связано с моей программой). Наконец, мы возвращаем объект узла.

Технически, узел XML, и мы передаем его на Handlexml Отказ Захватить все Назначение Экземпляры в XML, мы делаем это: xml.getelementsBytagname («Назначение») Отказ Затем мы передаем эту информацию для Handlapps метод. Да, здесь много проходящих вокруг различных ценностей и там. Он загнал меня с ума, пытаясь следовать за этим и отлаживать его позже. Во всяком случае, все Handlapps Метод представляет собой петлю по каждому назначению и позвонить в Handlapp Способ потянуть некоторую дополнительную информацию из него, добавьте данные в список и добавьте этот список в другой список. Идея состояла в том, чтобы оказаться в списке списков, которые провели все соответствующие данные о моих назначениях.

Вы заметите, что Handlapp Метод вызывает Полученность Метод, который называет GetText метод. Я не знаю, почему первоначальный автор сделал это таким образом. Я бы только что позвонил GetText Метод и пропущено GetELement One. Я думаю, что это может быть упражнение для вас, дорогой читатель.

Теперь вы знаете основы разборки с миниинком. Лично мне никогда не понравился этот метод, поэтому я решил попытаться придумать чистый способ разобраться XML с Minikom.

Сделать миниинком легче следовать

Я не собираюсь утверждать, что мой код – это хорошо, но я скажу, что я думаю, что я придумал чем-то намного проще следовать. Я уверен, что некоторые будут утверждать, что код не такой гибкий, а ну хорошо. Вот новый пример XML, который мы будем анализировать (найдено на MSDN ):



   
      Gambardella, Matthew
      XML Developer's Guide
      Computer
      44.95
      2000-10-01
      An in-depth look at creating applications 
      with XML.
   
   
      Ralls, Kim
      Midnight Rain
      Fantasy
      5.95
      2000-12-16
      A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.
   
   
      Corets, Eva
      Maeve Ascendant
      Fantasy
      5.95
      2000-11-17
      After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.
   
   
      Corets, Eva
      Oberon's Legacy
      Fantasy
      5.95
      2001-03-10
      In post-apocalypse England, the mysterious 
      agent known only as Oberon helps to create a new life 
      for the inhabitants of London. Sequel to Maeve 
      Ascendant.
   
   
      Corets, Eva
      The Sundered Grail
      Fantasy
      5.95
      2001-09-10
      The two daughters of Maeve, half-sisters, 
      battle one another for control of England. Sequel to 
      Oberon's Legacy.
   
   
      Randall, Cynthia
      Lover Birds
      Romance
      4.95
      2000-09-02
      When Carla meets Paul at an ornithology 
      conference, tempers fly as feathers get ruffled.
   
   
      Thurman, Paula
      Splish Splash
      Romance
      4.95
      2000-11-02
      A deep sea diver finds true love twenty 
      thousand leagues beneath the sea.
   
   
      Knorr, Stefan
      Creepy Crawlies
      Horror
      4.95
      2000-12-06
      An anthology of horror stories about roaches,
      centipedes, scorpions  and other insects.
   
   
      Kress, Peter
      Paradox Lost
      Science Fiction
      6.95
      2000-11-02
      After an inadvertant trip through a Heisenberg
      Uncertainty Device, James Salway discovers the problems 
      of being quantum.
   
   
      O'Brien, Tim
      Microsoft .NET: The Programming Bible
      Computer
      36.95
      2000-12-09
      Microsoft's .NET initiative is explored in 
      detail in this deep programmer's reference.
   
   
      O'Brien, Tim
      MSXML3: A Comprehensive Guide
      Computer
      36.95
      2000-12-01
      The Microsoft MSXML3 parser is covered in 
      detail, with attention to XML DOM interfaces, XSLT processing, 
      SAX and more.
   
   
      Galos, Mike
      Visual Studio 7: A Comprehensive Guide
      Computer
      49.95
      2001-04-16
      Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are 
      integrated into a comprehensive development 
      environment.
   

Для этого примера мы просто анализируем XML, извлеките названия книги и распечатайте их в STDOUT. Вы готовы? Вот так!

import xml.dom.minidom as minidom

#----------------------------------------------------------------------
def getTitles(xml):
    """
    Print out all titles found in xml
    """
    doc = minidom.parse(xml)
    node = doc.documentElement
    books = doc.getElementsByTagName("book")
    
    titles = []
    for book in books:
        titleObj = book.getElementsByTagName("title")[0]
        titles.append(titleObj)
        
    for title in titles:
        nodes = title.childNodes
        for node in nodes:
            if node.nodeType == node.TEXT_NODE:
                print node.data

if __name__ == "__main__":
    document = 'example.xml'
    getTitles(document)

Этот код является только одной короткой функцией, которая принимает один аргумент, файл XML. Мы импортируем модуль Minikom и дайте ему одно и то же имя, чтобы облегчить ссылку. Затем мы разбираем XML. Первые две строки в функции почти такие же, как предыдущий пример. Мы используем getelementsbytagname Чтобы схватить части XML, которую мы хотим, то итерации за счет результата и извлеките от них названия книги. Это фактически извлекает название объектов, поэтому нам нужно и повторить это и вытащить простой текст, который является тем, что второе вложенное для петля для.

Вот и все. Нету больше.

Обертывание

Ну, я надеюсь, что эта бессвязная статья научила вам вещь или две о разборке XML с помощью встроенного анализатора XML Python. Мы будем смотреть на XML разбираться в будущих статьях. Если у вас есть метод или модуль, который вам нравится, не стесняйтесь указывать мне, и я посмотрю.

Дополнительное чтение