Считывает пример xml и конвертирует его в 2 .sav-файла
Это пример файла XML для чтения данным скриптом: Read Sample XML file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | # -*- coding: cp1251 -*- # Источники: Hetland p. 427 (Beginning Python From Novice to Professional) # Глава 24 (Python in a Nutshel), Alex Martelli # Автор: Raynald Levesque, август 2008. # Перевод: А. Балабанов, 31.07.2009. # Проверено: Python 2.4.3 (IDLE 1.1.3), SPSS 15.0.1.1. # Размещение: http://www.spsstools.ru/Python/ReadSampleXMLfile.txt (.py) # Пример данных - .../sample.xml. # Цель решения - продемонстрировать импорт из .xml-файлов в SPSS посредством Python. # Задачи программы - извлечь данные из .xml-файла, поместить их в текстовые файлы с табуляцией в качестве # разделителей, затем - прочесть эти файлы синтаксисом SPSS. Все действия, в том числе - заключительная отсылка синтаксиса # в SPSS на исполнение производится в Питоне (например, из IDE-редактора, в который будет загружен данные .py-файл). При этом # SPSS должен быть запущен - примеч. перев. # Особенности примера. Данные, по-видимому, относятся к протоколированию футбольных матчей. Файл содержит 2 вида записей: action_log #(тип 1) - данные, характеризующие игру (команды, лига, время начала и конца матча) и вложенные записи action (либо Deletedaction) (типы 2, 3) - данные, # характеризующие ход конкретной игры: тип действия, взаимодействующие игроки, место (координаты поля) и т.д. # Т.е. данные представлены в иерархическом виде. В записях типа 2 состав элементов, содержащих данные, непостоянен: время от времени # могут появляться элементы subtype, c1, c2, c3, которые нет в большинстве записей action. Соответственно, разборщик, запрограммированный # в классе DataHandler должен учесть все эти особенности. Записи типа 1 помещаются в файл с именем samleLog.txt (2 записи), # записи типов 2, 3 - в файл с именем sampleAction.txt (23 записи). Вложенность записей action в записи action_log фиксируется в переменных # logID/id в обоих файлах. После импорта в SPSS файлы сохраняются в формате .sav - примеч. перев. from xml.sax.handler import ContentHandler from xml.sax import parse import spss # Укажите свои параметры: путь и имя файла fpath=r'C:/temp' fname=r'sample.xml' # прилагающийся .xml-файл примера xmlFile = r'%(fpath)s/%(fname)s' % vars() class DataHandler(ContentHandler): """Управляет процессом извлечения данных и организует их хранение в массиве """ in_extract = False # инициализация экземпляра класса def __init__(self, extract, wantList): ContentHandler.__init__(self) self.extract = extract self.data = [] self.nome="no" self.wantList = wantList # следующие 2 строки были скопированы из XML-файла и очищены от лишних символов - получили списки переменных self.action_logAtt = 'id team1 team1_name team2 team2_name league league_id \\ date matchday season season_code start1 start2'.split() self.actionAtt = 'aid action_code activitytype result id minute second \\ field_position receiver team_id x y z pace last_modified'.split() self.DeletedactionAtt = self.actionAtt # в записях типа action (тип 2) время от времени встречаются также и такие переменные: self.actionOpt ='subtype c1 c2 c3'.split() self.first_Action = True self.first_Log = True # Определяем действия, которые должны выполняться при возникновении событий startElement, endElement, characters. # Указанные события генерируются классом ContentHandler подключенного выше модуля xml.sax.handler. # Такая возможность позволяет нам "вмешиваться" в процесс разбора XML-структуры и решать, что делать с той или иной порцией данных. def startElement(self, name, attrs): self.in_extract = name in self.wantList # print name, attrs.keys() # если имя очередного атрибута находится в списке wantList (в перечне элементов, которые хотим извлечь)... if self.in_extract: self.nome = name if name== 'action_log': self.data=["1\\t"] #тип записи = 1 (характеристика игры) и табулятор как разделитель # через табулятор в цикле соединяем значения всех переменных, относящихся к этой записи self.data.extend(["%s\\t" % attrs.getValue(att) for att in self.action_logAtt]) self.action_logID=attrs.getValue('id') # будет добавлена в начале каждой записи-наследника (см. типы 2, 3) elif name == 'action': self.data=["2\\t", self.action_logID + '\\t'] #тип записи = 2 (характеристика событий в игре) # особая обработка записей с дополнительными ключами/переменными subtype, c1, c2, c3 # делаем заготовку массива dataOpt c количеством значков табуляции по числу ключей # (т.к. наперед еще неизвестно, будет ли запись содержать тот или иной ключ) # это позволит в следующем цикле при нахождении ключа поместить его в "свою" колонку self.dataOpt=['\\t']*len(self.actionOpt) for idx,attrib in enumerate(self.actionOpt): if attrs.has_key(attrib): self.dataOpt[idx] = attrs.getValue(attrib) + '\\t' # формируем основной массив, как и для типа 1 self.data.extend(["%s\\t" % attrs.getValue(att) for att in self.actionAtt]) # соединяем основной и дополнительный массивы self.data.extend(self.dataOpt ) elif name == 'Deletedaction': self.data=["3\\t", self.action_logID + '\\t'] #тип записи = 3 (характеристика событий в игре с пометкой Deleted - определяем как тип 3) self.data.extend(["%s\\t" % attrs.getValue(att) for att in self.DeletedactionAtt]) # Заготовка имен переменных для последующей записи в табулированные файлы if self.first_Log: # extract[0] будет содержать имена переменных и данные из 1-й XML-записи первого типа vnames=['recType'] vnames.extend(self.action_logAtt) vnames=["%s\\t" % v for v in vnames] vnames.append('\\n') # перевод строки/возврат каретки vnames.extend(self.data) # добавляем извлеченные данные во вторую строку self.data=vnames # обратный обмен содержимым (т.к. ниже мы помещаем # результат в массив extract именно из массива data). self.first_Log = False # это чтобы не возвращаться сюда ещё раз, и не формировать заголовочную строку с именами # переменных снова и снова # extract[1] будет содержать имена переменных и данные из 1-й XML-записи второго/третьего типа elif self.first_Action and name in ['action','Deletedaction']: vnames=['recType','logID'] vnames.extend(self.actionAtt) vnames.extend(self.actionOpt) vnames=["%s\\t" % v for v in vnames] vnames.append('\\n') vnames.extend(self.data) self.data = vnames self.first_Action = False text = ''.join(self.data) + '\\n' # добавляем перевод строки self.extract.append(text) # формируем очередной элемент массива extract def endElement(self,name): # встретили закрывающий элемент if name in self.wantList: self.data = [] # если это тот элемент, который разбирали, то очищаем массив данных и ставим признак того, # что мы находимся вне желаемого ключа self.in_extract = False def characters(self,string): # обработка строковых данных, встречающихся вне ключей if self.in_extract: # если находимся внутри желаемого ключа, self.data.append(string) # В данном случае обработка данного события, вероятно, излишняя. # В файле с примером это событие вызывают лишь символы перевода строки. Но в этих случаях # все нужные данные в self.data уже сформированы и выгружены в self.extract. # для создания табулированных файлов используем свой класс # Примеч.: если бы мы имели дело с разбором очень большого XML-файла, было бы предпочтительнее организовывать запись # в табулированные текстовые файлы непосредственно по ходу разбора (парсинга) XML-файла, т.е. прописать это в классе DataHandler. extract = [] # инициализируем массив, где будут храниться извлеченные данные wantList=['action_log','action','Deletedaction'] # перечисляем элементы, которые хотим извлечь parse(xmlFile, DataHandler(extract, wantList)) # извлекаем данные из XML-файла (работает парсинг и класс DataHandler) nameroot = fname[:fname.find('.')] # sample.xml --> sample (обрезаем расширение) fLogName = r'%(fpath)s/%(nameroot)sLog' % vars() # --> путь/sampleLog fActionName = r'%(fpath)s/%(nameroot)sAction' % vars() # --> путь/sampleAction fLog = open(fLogName+'.txt','w') # файл с содержимым action_log +'.txt' fAction = open(fActionName+'.txt','w') # файл с содержимым action/Deletedaction +'.txt' # print extract try: for (i,s) in enumerate(extract): if len(s)> 0: s2 = s.encode('iso8859-1') # перед записью в файл перекодируем строку, если в данных есть символы ASCII c кодами вне 0-128 # кодировка совпадает с той, что находится в заголовке .xml-файла. if s[0] in ['2','3'] or i==1: # вторая запись содержит имена переменных для файла action fAction.write(s2) elif s[0] == '1' or i == 0: # первая запись содержит имена переменных для файла action_log fLog.write(s2) finally: fAction.close() fLog.close() # Полученные табулированные файлы далее будут прочитаны в SPSS. # Ниже приводится синтаксис, созданный при помощи мастера импорта текстовых файлов, # и вставленный сюда с небольшими правками, чтобы сделать процесс импорта # полностью автоматизированным. Последняя команда spss.Submit посылает в SPSS # команды на импорт текстовых табулированных файлов и сохранение их в формате .sav. cmd=r""" SET PRINTBACK=YES /MPRINT=YES. DATASET CLOSE ALL. GET DATA /TYPE = TXT /FILE = "%(fLogName)s.txt" /DELCASE = LINE /DELIMITERS = "\\t" /ARRANGEMENT = DELIMITED /FIRSTCASE = 2 /IMPORTCASE = ALL /VARIABLES = recType F1.0 id F6.0 team1 F3.0 team1_name A19 team2 F3.0 team2_name A16 league A14 league_id F1.0 date A22 matchday F2.0 season A9 season_code F2.0 start1 A22 start2 A22. CACHE. SAVE OUTFILE= "%(fLogName)s.sav". GET DATA /TYPE = TXT /FILE = "%(fActionName)s.txt" /DELCASE = LINE /DELIMITERS = "\\t" /ARRANGEMENT = DELIMITED /FIRSTCASE = 2 /IMPORTCASE = ALL /VARIABLES = recType F1.0 logID F6.0 aid F7.0 action_code A4 activitytype F2.0 result F1.0 id F2.0 minute F2.0 second F2.0 field_position F2.0 receiver F5.0 team_id F3.0 x F5.3 y F5.3 z F5.3 pace F5.3 last_modified A22 subtype F2.0 c1 F1.0 c2 F1.0 c3 F1.0 . CACHE. SAVE OUTFILE="%(fActionName)s.sav". """ % vars() # сформировали синтаксис SPSS для считки и сохранения в .sav табулированных файлов. spss.Submit(cmd) # отправили синтаксис на исполнение |
Related pages
...