Синтаксического анализа XML-схем и создания XML из плоских файлов


Я новичок в Python и пришлось создать парсер схемы извлекать информацию об атрибутах и сложных типов и т. д. а затем преобразовать данные из плоских файлов в формате XML. Мы обрабатывать большое количество данных и я столкнуться с некоторыми проблемами, как только мы проходим около 1 миллионов обработанных записей.

Я ищу какие-либо предложения по стилю код, лучшие практики Python и т. д. что будет прибраться немного и увеличить эффективность.

Вот та часть, которая тянет в схеме:

import csv, ConfigParser, re, datetime, time
from lxml import etree

elemdict = {}
parser = etree.XMLParser()
data = etree.parse(open("testschema.xsd"),parser)
root = data.getroot()
version = root.get("version")

rootelement = root[0]

elements = rootelement[0][0].getchildren()

for e in elements:
    ename = e.get("name")
    elemdict[ename] = [] 
    subelements = e[0][0].getchildren()
    for se in subelements:
        elemdict[ename].append(se.attrib)

specials = root.getchildren()[1:]

specialtypes = {}

for sp in specials:
    sname = sp.get("name") 
    specialtypes[sname] = {}
    specialtypes[sname]["type"] = sp.tag.split('}')[-1] #removes namespace to get either complex or simple type, another option here would be to use xpath('local-name()') or remove the first 34 characters from the tag, none of them really clean options
    typeelements = sp.getchildren()[0].getchildren()
    specialtypes[sname]["details"] = []
    if specialtypes[sname]["type"] == "complexType":
        specialtypes[sname]["requireds"] = []
        for t in typeelements:
            specialtypes[sname]["details"].append(t.get("name"))
            if (not "minOccurs" in t.attrib) or int(t.get("minOccurs"))>0:
                specialtypes[sname]["requireds"].append(t.get("name"))
    else:
        for t in typeelements:
            specialtypes[sname]["details"].append(t.get("value"))

Что тянет вся информация в двух словарях, elemdict и specialtypes. Специальные типы включает перечислений и сложные типы.

Вот код, который создает и возвращает XML-элементов, где Д является корневым элементом, datainput это линия, мы были получены из файла, имя - имя элемента, а обязательное перечень обязательных полей для элемента:

def addData(d, datainput, name, requireds):

try:
    datavals = dict((k.lower().replace(" ","_"),v) for k,v in datainput.iteritems()) #lower case all the keys for consistency
except AttributeError:
    print "Invalid row, skipping: " + str(datainput)
    return

for i in range(len(requireds)):
    rname = requireds[i]["name"]
    rtype = requireds[i]["type"]
    if rtype[0:3] != "xs:": #if no xs: prefix, element is a complex element of one of our types
        for j in range(len(specialtypes[rtype]["requireds"])):
            spname = specialtypes[rtype]["requireds"][j]
            if not((rname + "_" + spname) in datavals) or len(datavals[(rname + "_" + spname)])<=0:
                print "missing attributes for complex element " + rname + " in values " + str(datavals) + ", returning"
                return
    elif not(rname in datavals) or len(datavals[rname])<=0:
        print "no " + rname + " in values " + str(datavals) + ", returning"
        return


element = etree.SubElement(d, name)
element.set("id", datavals["id"])
for i in range(len(elemdict[name])):
    cname = elemdict[name][i]["name"]
    ctype = elemdict[name][i]["type"]
    if ctype[0:3] != "xs:" and specialtypes[ctype]["type"] == "complexType": #if the type does not start with and xml type and is a complex type specified by us

        validComplex = True
        for j in range(len(specialtypes[ctype]["requireds"])):
            spname = specialtypes[ctype]["requireds"][j]
            if not((cname + "_" + spname) in datavals) or len(datavals[(cname + "_" + spname)])<=0:
                validComplex = False
                break
        if validComplex:
            temp = etree.SubElement(element, cname)
            for d in specialtypes[ctype]["details"]:
                if (cname + "_" + d) in datavals and len(datavals[(cname + "_" + d)]) > 0:
                    tempsubelem = etree.SubElement(temp, d)
                    tempsubelem.text = datavals[(cname + "_" + d)]

    elif cname in datavals and len(datavals[cname]) > 0:
        temp = etree.SubElement(element, cname)
        try:
            if ctype == "xs:date":
                temp.text = str(datetime.date(*time.strptime(datavals[cname],dateformat)[0:3]))
            else:   
                temp.text = datavals[cname]
        except ValueError:
            temp.text = removeNonAscii(datavals[cname])


13574
3
задан 21 июля 2011 в 04:07 Источник Поделиться
Комментарии
1 ответ

Вы, возможно, захотите пересмотреть ваш подход коренным образом, если вы хотите создать миллионы строк XML.


  • Определить классы в Python, чтобы содержать ваши реальные данные. Это должна быть абсолютно правильным, основанным на обычной обработки в Python. Нет на основе xsd просмотра или проверки или проверка диапазона или ничего. Только Python. Данные приложения должны быть в обычные старые объекты Python (Попо).

  • Написать "сериализатор", который создает XML-файл от простых объектов в Python. Поскольку объекты Python уже абсолютно правильно, на выходе XML будет абсолютно правильно.

    Или найти seraializer. http://coder.cl/products/pyxser/ Django есть один.

    https://stackoverflow.com/questions/1500575/python-xml-serializers


Как только вы имеете эту инфраструктуру классов Python, которые производят XML в место, тогда вы делаете следующее.


  • Переписать парсер xsd-файл так, что он создает свой простой старый объект Python определения классов из xsd. Это xsd-файл->питон переводчик.

Теперь вы делаете большую часть работы в Python. Миллионы строк в простые определения на языке Python легко. XML-это просто сериализованные объекты Python. Поскольку xsd не применяется, это тоже легко.

Далее (и самое главное) вы делаете один раз-только преобразование xsd для питона.

Посмотрите на этом сайте StackOverflow вопрос, в каком направлении отправиться. https://stackoverflow.com/questions/1072853/convert-xsd-to-python-class

5
ответ дан 21 июля 2011 в 09:07 Источник Поделиться