diff --git a/src/main.py b/src/main.py index f99322e..8054cc2 100755 --- a/src/main.py +++ b/src/main.py @@ -7,13 +7,14 @@ __version__ = "0.1.0" __license__ = "Apache" +from qti_parser import question_type import argparse import json from logzero import logger from lxml import etree qti_resource = { - 'assessments': [] + 'assessment': [] } def main(args): @@ -28,23 +29,32 @@ def main(args): this_assessment = { 'id': xml_resource.get("identifier"), 'title': '', - 'questions': [] + 'question': [] } this_assessment_xml = this_assessment['id'] + "/" + this_assessment['id'] + ".xml" for xml_item in etree.parse(this_assessment_xml).getroot().findall(".//{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}item"): + xml_item_metadata = xml_item.find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}itemmetadata/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}qtimetadata") this_question = { - 'id': xml_item.get("ident"), - 'text': xml_item.find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}presentation/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}material/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}mattext").text, - 'answers': [] + 'id': str(xml_item.get("ident")), + 'question_type': xml_item_metadata.find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}qtimetadatafield[{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}fieldlabel = 'question_type']/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}fieldentry").text, + 'points_possible': xml_item_metadata.find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}qtimetadatafield[{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}fieldlabel = 'points_possible']/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}fieldentry").text, + 'text': xml_item.find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}presentation/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}material/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}mattext").text } - this_assessment['questions'].append(this_question) - this_assessment['title'] = etree.parse(this_assessment_xml).getroot().find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}assessment").get("title") - # multiple_choice_question - # short_answer_question + if this_question['question_type'] == "multiple_choice_question": + this_question['answer'] = question_type.multiple_choice.get_answers(xml_item) + elif this_question['question_type'] == "true_false_question": + this_question['answer'] = question_type.true_false.get_answers(xml_item) + elif this_question['question_type'] == "multiple_answers_question": + this_question['answer'] = question_type.multiple_answers.get_answers(xml_item) + elif this_question['question_type'] == "short_answer_question": + this_question['answer'] = question_type.short_answer.get_answers(xml_item) + + this_assessment['question'].append(this_question) + this_assessment['title'] = etree.parse(this_assessment_xml).getroot().find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}assessment").get("title") - qti_resource['assessments'].append(this_assessment) + qti_resource['assessment'].append(this_assessment) qti_resource_json = json.dumps(qti_resource, indent = 2) print(qti_resource_json) diff --git a/src/parser/imsmanifest.py b/src/parser/imsmanifest.py deleted file mode 100644 index 6574fa0..0000000 --- a/src/parser/imsmanifest.py +++ /dev/null @@ -1 +0,0 @@ -# http://www.imsglobal.org/xsd/imsccv1p1/imscp_v1p1 diff --git a/src/qti_parser/__init__.py b/src/qti_parser/__init__.py new file mode 100644 index 0000000..c99568f --- /dev/null +++ b/src/qti_parser/__init__.py @@ -0,0 +1 @@ +from . import question_type diff --git a/src/qti_parser/question_type/__init__.py b/src/qti_parser/question_type/__init__.py new file mode 100644 index 0000000..555d2ee --- /dev/null +++ b/src/qti_parser/question_type/__init__.py @@ -0,0 +1,9 @@ +""" +Question Types +""" + +from . import multiple_answers +from . import multiple_choice +from . import true_false +from . import short_answer + diff --git a/src/qti_parser/question_type/multiple_answers.py b/src/qti_parser/question_type/multiple_answers.py new file mode 100644 index 0000000..853ce12 --- /dev/null +++ b/src/qti_parser/question_type/multiple_answers.py @@ -0,0 +1,29 @@ +""" +Multiple Answers +""" + +from lxml import etree +from logzero import logger + +def get_answers(xml): + """ Return an array of possible answers """ + answers = [] + correct_answers = [] + + for id in xml.findall(".//{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}conditionvar/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}and/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}varequal"): + correct_answers.append(id.text) + + try: + for xml_answer_item in xml.findall(".//{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}response_label"): + answers.append( + { + 'id': xml_answer_item.get("ident"), + 'text': xml_answer_item.find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}material/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}mattext").text, + 'correct': True if xml_answer_item.get("ident") in correct_answers else False + } + ) + except OSError as e: + logger.error("%s", e) + except etree.ParseError as e: + logger.error("XML parser error: %s", e) + return answers \ No newline at end of file diff --git a/src/qti_parser/question_type/multiple_choice.py b/src/qti_parser/question_type/multiple_choice.py new file mode 100644 index 0000000..5aeb15a --- /dev/null +++ b/src/qti_parser/question_type/multiple_choice.py @@ -0,0 +1,29 @@ +""" +Multiple Choice +""" + +from lxml import etree +from logzero import logger + +def get_answers(xml): + """ Return an array of possible answers """ + answers = [] + correct_answers = [] + + for id in xml.findall(".//{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}varequal"): + correct_answers.append(id.text) + + try: + for xml_answer_item in xml.findall(".//{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}response_label"): + answers.append( + { + 'id': xml_answer_item.get("ident"), + 'text': xml_answer_item.find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}material/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}mattext").text, + 'correct': True if xml_answer_item.get("ident") in correct_answers else False + } + ) + except OSError as e: + logger.error("%s", e) + except etree.ParseError as e: + logger.error("XML parser error: %s", e) + return answers \ No newline at end of file diff --git a/src/qti_parser/question_type/short_answer.py b/src/qti_parser/question_type/short_answer.py new file mode 100644 index 0000000..f9c171d --- /dev/null +++ b/src/qti_parser/question_type/short_answer.py @@ -0,0 +1,27 @@ +""" +Short Answer +""" + +from lxml import etree +from logzero import logger + +def get_answers(xml): + """ Return an array of possible answers """ + answers = [] + i = 0 + + try: + for xml_answer_item in xml.findall(".//{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}varequal"): + i += 1 + answers.append( + { + 'id': str(i), + 'text': xml_answer_item.text, + 'correct': True + } + ) + except OSError as e: + logger.error("%s", e) + except etree.ParseError as e: + logger.error("XML parser error: %s", e) + return answers \ No newline at end of file diff --git a/src/qti_parser/question_type/true_false.py b/src/qti_parser/question_type/true_false.py new file mode 100644 index 0000000..74e6da6 --- /dev/null +++ b/src/qti_parser/question_type/true_false.py @@ -0,0 +1,29 @@ +""" +True or False +""" + +from lxml import etree +from logzero import logger + +def get_answers(xml): + """ Return an array of possible answers """ + answers = [] + correct_answers = [] + + for id in xml.findall(".//{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}varequal"): + correct_answers.append(id.text) + + try: + for xml_answer_item in xml.findall(".//{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}response_label"): + answers.append( + { + 'id': xml_answer_item.get("ident"), + 'text': xml_answer_item.find("{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}material/{http://www.imsglobal.org/xsd/ims_qtiasiv1p2}mattext").text, + 'correct': True if xml_answer_item.get("ident") in correct_answers else False + } + ) + except OSError as e: + logger.error("%s", e) + except etree.ParseError as e: + logger.error("XML parser error: %s", e) + return answers \ No newline at end of file