Автор оригинала: 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 разбираться в будущих статьях. Если у вас есть метод или модуль, который вам нравится, не стесняйтесь указывать мне, и я посмотрю.
Дополнительное чтение
- Python Minikom Официальная документация
- Python и XML Wiki Page
- Другие встроенные XML-анализаторы Python: ElementTree , Сакс, Expat и домочка