Форум сайта python.su
У меня уже давно сформировалось стойкое ощущение, что вы пытаетесь превратить простой парсинг в нечто суперсложное. Ваша новая идея это подтверждает.
Давайте набросаю вам прототипчик? У меня только один вопрос - одни и те же тэги на разных уровнях могут быть? Я спрашиваю только о тегах типа ‘Данные’, внутри которых есть другие, внутренности которых нужно собирать. Если эти тэги уникальны, то отслеживать уровни вообще не нужно. Если они могут таки повторяться на разных уровнях, тогда нужно делать так, как я написал.'
Офлайн
буду не против, т.к. не до конца понимаю Ваш код.
В файле содержаться сотни тегов <Данные>, сотни тегов <Отчеты> и такое же количество <Документов>.
в исходном xml в теги типа <Данные> всегда входят какие либо другие теги, их набор статичен для каждого из <Данных>, но отличается для <Отчетов> и <Документов> (для каждого из которых, в свою очередь они свои и также статичны). Теги, вложенные в теги типа <Данные>, также всегда наполнены определенным набором других тегов. Последние, в свою очередь, не обременены обязанностями быть наполненными и/или находиться там, но какое то их количество всегда там присутствует.
“Если эти тэги уникальны, то отслеживать уровни вообще не нужно. Если они могут таки повторяться на разных уровнях, тогда нужно делать так, как я написал”
Не могу сказать что не понимаю Вас, но все же не до конца.
Офлайн
Да, с пониманием у нас туго. Давайте на примере тэга ‘Данные’.
Вот такой xml:
<main>
<Данные>
<ДатаНачала>22.03.2011</ДатаНачала>
<Назначение>Торговля</Назначение>
<Комментарии/>
<ДатаОкончания>22.03.2011</ДатаОкончания>
</Данные>
<какой-то другой тэг>
<Данные>
<Что-то>содержимое чего-то</Что-то>
</Данные>
</какой-то другой тэг>
</main>
Реален? Или все-таки тэг ‘Данные’ всегда содержит тэги ‘ДатаНачала’, ‘Назначение’, ‘Комментарии’ и ‘ДатаОкончания’?
Может ли встречаться тэг ‘Данные’ на разных уровнях? Содержимое тегов внутри тэга ‘Данные’ складывается в одну и ту же таблицу в базу или в разные в зависимости от уровня, на котором находится тэг ‘Данные’?
Нарисуйте мне, пожалуйста, пример вашего многоуровневого xmlя с разными комбинациями тэгов и напишите какие тэги в какие таблицы и поля складывать. Я вам за это нарисую прототипчик, который будет его в один проход обрабатывать.
Отредактировано (Фев. 16, 2012 19:17:22)
Офлайн
Вот вам мой прототипчик. Может с кодом будет проще. Я взял за основу простой вариант - интересующие нас тэги могут встречаться на любом уровне, но имеют одну и ту же структуру. Вместо собственно записи в базу я пишу в какую таблицу и в какие поля писать данные.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from xml.sax.handler import ContentHandler
from xml import sax
class Handler(ContentHandler):
def __init__(self, fields, callback):
ContentHandler.__init__(self)
self.results = dict([(name, {}) for name in fields])
self.callback = callback
self.target = None
self.current = None
def startElement(self, name, attrs):
self.current = name
if name in self.results:
self.target = name
def endElement(self, name):
self.current = None
if name in self.results:
self.callback(self.target, self.results[self.target])
self.results[self.target] = {}
self.target = None
def characters(self, content):
if self.target:
self.results[self.target][self.current] = content
class DBWriter():
def __init__(self, rules):
self.rules = rules
def write(self, name, data):
rules = self.rules[name]
print "Пришло", name
print "Пишем в таблицу '%s'" % rules["table"]
for key, fname in rules["fields"].iteritems():
print "В поле", fname, "запишем", data[key]
print ""
if __name__ == '__main__':
writer = DBWriter({u"Данные": {"table": "tab_data",
"fields": {u"ДатаНачала": "begin_date",
u"Назначение": "target",
u"ДатаОкончания": "end_date"}},
u"Документ": {"table": "tab_doc",
"fields": {u"ДатаСоздания": "create_date",
u"Наименование": "name",
u"Состояние": "status"}}})
parser = sax.make_parser()
handler = Handler((u"Данные", u"Документ"), writer.write)
parser.setContentHandler(handler)
parser.parse("new2.xml")
<?xml version="1.0" encoding="utf-8"?>
<main>
<Данные>
<ДатаНачала>22.03.2011</ДатаНачала>
<Назначение>Торговля</Назначение>
<Комментарии/>
<ДатаОкончания>22.03.2011</ДатаОкончания>
</Данные>
<Отчет>
<ДатаНачала>08.09.2011</ДатаНачала>
<ТипОтчета>Годовой</ТипОтчета>
<Состояние>Готов</Состояние>
<Участники>
<Лицо>
<Должность>Главный бухгалтер</Должность>
<ФИО>Жожо Клара Максимовна</ФИО>
<СтепеньОтветственности>Основная составительная</СтепеньОтветственности>
</Лицо>
<Лицо>
<Должность>Бухгалтер</Должность>
<ФИО>Плеханова Елена Дмитриевна</ФИО>
<СтепеньОтветственности>Частичная</СтепеньОтветственности>
</Лицо>
</Участники>
<ОтветственноеЛицо>Директор</ОтветственноеЛицо>
<ФИО>Кузьмин Герасим Аркадъевич</ФИО>
<Параметр1>Ложь</Параметр1>
<Параметр2>Ложь</Параметр2>
<Параметр3>Истина</Параметр3>
<Параметр4>Ложь</Параметр4>
<Данные>
<ДатаНачала>23.04.2012</ДатаНачала>
<Назначение>Обмен</Назначение>
<Комментарии/>
<ДатаОкончания>24.05.2012</ДатаОкончания>
</Данные>
</Отчет>
<Документ>
<ДатаСоздания>04.11.2011</ДатаСоздания>
<Наименование>Договор №07</Наименование>
<Состояние>В доработке</Состояние>
<Автор>
<Должность>Директор по внешней торговле</Должность>
<ФИО>Лобачев Олег Алексеевич</ФИО>
</Автор>
</Документ>
</main>
Офлайн
EdНет. <Данные> может содержать определенный набор тегов, в каком то из тегов <Данные> могут быть все его теги, а в каком то только один из всего набора (это значит, что отсутствующие теги не содержат никакой информации, поэтому они отсутствуют)
Вот такой xml:
<main>
<Данные>
<ДатаНачала>22.03.2011</ДатаНачала>
<Назначение>Торговля</Назначение>
<Комментарии/>
<ДатаОкончания>22.03.2011</ДатаОкончания>
</Данные>
<какой-то другой тэг>
<Данные>
<Что-то>содержимое чего-то</Что-то>
</Данные>
</какой-то другой тэг>
</main>
Реален? Или все-таки тэг ‘Данные’ всегда содержит тэги ‘ДатаНачала’, ‘Назначение’, ‘Комментарии’ и ‘ДатаОкончания’?
EdНет.
Может ли встречаться тэг ‘Данные’ на разных уровнях?
EdВложенные в <Данные> теги идут в разные таблици одной базы в зависимости от вложенности.
Содержимое тегов внутри тэга ‘Данные’ складывается в одну и ту же таблицу в базу или в разные в зависимости от уровня, на котором находится тэг ‘Данные’?
EdXML:
Нарисуйте мне, пожалуйста, пример вашего многоуровневого xml с разными комбинациями тэгов и напишите какие тэги в какие таблицы и поля складывать. Я вам за это нарисую прототипчик, который будет его в один проход обрабатывать.
Отредактировано (Фев. 17, 2012 10:41:16)
Офлайн
На первый взгляд мое решение подходит. Не совсем понятно что делать с тэгами типа Parents, их же не сложишь в одно поле, поскольку они в себе содержат другие тэги.
Давайте так - вы попробуете использовать мой код с этим xml, а если что-то не будет получаться будете здесь спрашивать. Изменения поначалу будут касаться только входных данных, вот вам пример начала:
writer = DBWriter({u"Справочник.Номенклатура": {"table": "Spravochnik.Nomenclatura",
"fields": {u"IDD": "IDD",
u"Код": "Cod",
u"Наименование": "Naimenovanie",
u"ПометкаУдаления": "PometkaUdaleniya",
и так далее
Офлайн
СПАСИБО!!!!!! ОгромноЕ! Сейчас же засяду)
Определилось, что надо делать для <Параметр N>: для них (для каждого в отдельности) созданы таблицы с полями IDD (IDD присвоенный при создании записи внутри таблицы), IDDold (IDD с xml), Наименование, и в таблице Spravochnik.Nomenklatura идет поле Параметр N в каждой из которых указан IDDold для поиска нужной записи в таблице Параметр N.
Parents будет использоваться как указатель на родительскую таблицу (эту идею надо будет еще доработать)
Для НоменклатурнаяГруппа, также как и для Параметр N, будет создана отдельная таблица, и связь из Spravochnik.Nomenklatura с этой таблицей будет организована по полю IDDold.
Остальные вложенные пока обрабатывать не буду.
Вопрос: как в данном случае будет лучше организовать( для таких вложенных тегов как <Вид>, <IDD> и <Наименование> которые располагаются на последнем уровне вложенности) выгрузку в отдельные таблицы?
Создать отдельный класс для обработки всех Параметров и Номенклатурных групп, который будет отдельно их выдергивать и записывать в их таблицы? как рациональней?
Отредактировано (Фев. 17, 2012 13:23:45)
Офлайн
Прошу прощения, что не отвечал долго - был в отъезде на выходных. Ну как, что-нибудь получилось?
Насчет IDD и прочего не совсем понятно. Приведите конкретный пример. В какие таблицы для каких тэгов чего писать. Попробуйте сделать сами, скажите что получилось, а что нет.
И вообще сделайте для начала чтобы работало для простого случая. Я пока не видел никаких результатов.
Офлайн
Здравствуйте. Касательно Параметров:
В Параметр N могут входить такие поля, как: Вид, IDD (ранее присвоенный другой программой) и Наименование.
Для каждого из Параметров будет создано по таблице, а также в таблице Nomenklatura будут поля Параметр 1, Параметр2, … , Параметр 14, которые будут связаны с соответствующей таблицей по средствам db.ReferenceProperty().
Результаты
from xml.sax.handler import ContentHandler
from xml import sax
class Handler(ContentHandler):
def __init__(self, fields, callback):
ContentHandler.__init__(self)
self.results = dict()
self.callback = callback
self.target = None
self.current = None
self.in_NomenGroup = False
self.in_Vladelec = False
def startElement(self, name, attrs):
self.current = name
if name in self.results:
self.target = name
if name == ‘НоменклатурнаяГруппа’:
self.in_NomenGroup = True
if name == ‘Владелец’:
self.in_Vladelec = True
def endElement(self, name):
self.current = None
if name in self.results:
self.callback(self.target, self.results)
self.results = {}
self.target = None
def characters(self, content):
if self.target:
self.results = content
class DBWriter():
def __init__(self, rules):
self.rules = rules
def write(self, name, data):
rules = self.rules
# print “Пришло”, name
# print “Пишем в таблицу ‘%s’” % rules
for key, fname in rules.iteritems():
print “В поле”, fname, “запишем”, data
print “”
if __name__ == ‘__main__’:
writer = DBWriter({u“Справочник.Номенклатура”: {“table”: “Nom”,
“fields”: {u“IDD”: “IDD”,
u“Наименование”: “name”,
u“Родитель”: “idB”,
u“Параметр1”: “param 1”,
u“Параметр2”: “param 2”,
u“Параметр3”: “param 3”,
u“Параметр4”: “param 4”,
u“Параметр5”: “param 5”,
u“Параметр6”: “param 6”,
u“Параметр7”: “param 7”,
u“Параметр8”: “param 8”,
u“Параметр9”: “param 9”,
u“Параметр10”: “param 10”,
u“Параметр11”: “param 11”,
u“Параметр12”: “param 12”,
u“Параметр13”: “param 13”,
u“Параметр14”: “param 14”}},
u“ОписанияПараметров”: {“table”: “OpParam”,
“fields”: {u“IDD”: “idc”,
u“Код”: “numpar”,
u“Наименование”: “name”,
u“”: “status”}}})
parser = sax.make_parser()
handler = Handler((u“Номенклатура”, u“ОписанияПараметров”), writer.write)
parser.setContentHandler(handler)
parser.parse(“for_web.xml”)
Определилось кол-во видов нодов для обработки. Набор нужных тегов, которые содержаться в них, и в итоге:
стало очевидно, что этот подход не для моего случая, т.к.:
1) Нужно обрабарывать содержимое 2-4 основных тегов (наподобие “Номенклатура” или “ОписанияПараметров”);
2)В парсере должен быть предусмотрен легкий разбор подуровней (почти,предел есть всему)бесконечного кол-ва уровней вложенности, потому как исходный документ может немного меняться в сторону увеличения уровней вложенности, поэтому надо предусмотреть легкое добавление обработчика последнего(возможно нового) уровня. Руководитель рекомендует (читай: настаивает) на варианте подхода с выдиранием по 1му ноду (типа “Номенклатура”) в переменную, и обрабатывать этот кусочек отдельно, преимущество: - позволяет легко изменять кол-во обрабатываемых уровней, а также нодов.
Отредактировано (Фев. 27, 2012 11:40:06)
Офлайн
еще хотелось бы уточнить:
возможна ли запись куска файла (xml) в переменную или только освобожденной от тегов информации?
Если да, то каким путем стоит идти:
1) путь через работу с файлом как с файл-объектом, через open(filename) и т.п. (тут непонятно как он будет читать файл: каждый раз с самого начала?)
2) путь через многопотоковую организацию (но это, по-моему, край гемора переходящего в маразм)
3) не известный мне путь, выдирания из голого потока всего содежимого.
если нет, то как быть? можно, конечно, использовать Ваш метод записи данных, как именованных переменных, но тогда игнорируется условие, касательно большого количества уровней вложенности, о котором говорилось ранее (а соблюдение его очень важно).
Отредактировано (Фев. 27, 2012 10:08:54)
Офлайн