162 lines
4.7 KiB
Python
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()
|