wegen/sosci2word/sosci2word.py

162 lines
4.7 KiB
Python

#!/usr/bin/python3
#
# sosci2word - Einlesen eines SoSci-Fragebogens und umwandeln in ein Word-Dokument
#
# (c) 2023 Hermann Voßeler
# This code is free software and can be used under the terms of the MIT License.
#
import sys
from xml.etree import ElementTree
#-----------------------SETUP
SOSCI_XML='ThesisFragebogen.2023-04-19.xml'
WORD_TEMPLATE='Thesis-Fragebogen.docx'
WORD_OUTPUT='Thesis-Fragebogen-import.docx'
#-----------------------SETUP
def convertSosci2Word():
# Schritt-1 : alle Frage-Definitionen aufsammeln
collectQuestionDefinitions()
# Schritt-2 : die Fragen in der Reihenfolge vom Questionaire
## TODO
# Schritt-3 : Questionaire in das Word-Dokument ausgeben
## TODO
class QuestionElement:
def __init__(self, questionID, question):
self.qid = questionID
self.title = question.find('title').text
self.desc = question.find('description').text
def dumpBasis(self, type):
return "##--%s--##\ndes=%s\ntitle=%s" % (type, self.desc, self.title)
def dump(self):
return self.dumpBasis("Basis")
class LikertItem(QuestionElement):
def __init__(self, questionID, question):
QuestionElement.__init__(self, questionID, question)
self.labels = []
for entry in question.find('labels').findall('li'):
code = int(entry.get('i'))
text = entry.text
self.labels.append((code,text))
self.items = []
for item in question.findall('item'):
code = int(getSpecificID(item))
text = item.find('text').text
self.items.append((code,text))
def dump(self):
return ( self.dumpBasis('Likert')
+ "\nLabels: " + str(list("(%d,%s)" % (c,t) for c,t in self.labels))
+ "\nItems: " + str(list("(%d,%s)" % (c,t) for c,t in self.items))
)
class SelectItem(QuestionElement):
def __init__(self, questionID, question):
QuestionElement.__init__(self, questionID, question)
self.items = []
for item in question.findall('item'):
code = int(getSpecificID(item))
text = item.find('text').text
self.items.append((code,text))
def dump(self):
return ( self.dumpBasis('Select')
+ "\nItems: " + str(list("(%d,%s)" % (c,t) for c,t in self.items))
)
class TextElement(QuestionElement):
def __init__(self, questionID, question):
QuestionElement.__init__(self, questionID, question)
lead = question.find('lead')
if lead == None:
self.text = ""
else:
self.text = lead.text
def dump(self):
return ( self.dumpBasis('Text')
+ "\nText: " + self.text
)
def collectQuestionDefinitions():
#
questions = {}
#
root = ElementTree.parse(SOSCI_XML).getroot()
for section in root.findall('section'):
title = section.find('title')
id_prefix = getSpecificID(section)
print("Section: Title »%s« Prefix=%s" % (title.text,id_prefix))
for question in section.findall('question'):
title = question.find('title').text
desc = question.find('description').text
questionType = question.find('class').text
id_suffix = getSpecificID(question)
id_suffix = int(id_suffix)
questionID = "%s%02d" % (id_prefix, id_suffix)
if questionType == 'scale':
element = LikertItem(questionID, question)
elif questionType == 'select' or questionType == 'dropdown':
element = SelectItem(questionID, question)
elif questionType == 'TextContent':
element = TextElement(questionID, question)
elif questionType == 'checkbox':
pass # ignorieren wir
else:
__err("unbekannter QuestionType:"+questionType)
questions[questionID] = element
print(questions.keys())
for key in questions.keys():
quest = questions[key]
print("Question: ID=%s type=%s desc=%s" % (quest.qid, type(quest), quest.desc))
print(quest.dump())
# Hilfsmittel für SoSci-XML: extrahiert ein ID-Element, das eingeschachtelt in <attributes.specific> liegt
def getSpecificID(element):
attribspecific = element.find('attributes.specific')
return next(attr.text for attr in attribspecific.findall('attr') if attr.get('id') == 'id')
# ---- Hilfsfunktionen
def __err(text):
print('---FAILURE----------------------')
print(text)
print('abort.')
sys.exit(255)
if __name__=='__main__':
convertSosci2Word()