paul@682 | 1 | #!/usr/bin/env python |
paul@682 | 2 | |
paul@682 | 3 | """ |
paul@682 | 4 | Collect responses from multiple answer files. |
paul@682 | 5 | """ |
paul@682 | 6 | |
paul@682 | 7 | from XSLForms.Resources.WebResources import resources |
paul@682 | 8 | from glob import glob |
paul@682 | 9 | import os |
paul@682 | 10 | import libxml2dom |
paul@682 | 11 | |
paul@682 | 12 | question_path = "/questionnaire/question" |
paul@682 | 13 | |
paul@682 | 14 | def collect(questions, responses_dir): |
paul@682 | 15 | answers = {} |
paul@682 | 16 | for filename in glob(os.path.join(responses_dir, "distilled-*")): |
paul@682 | 17 | responses = libxml2dom.parse(filename) |
paul@682 | 18 | collect_answers(answers, questions, responses) |
paul@682 | 19 | return answers |
paul@682 | 20 | |
paul@682 | 21 | def collect_answers(answers, questions, responses): |
paul@682 | 22 | |
paul@682 | 23 | # Get a mapping from questions to responses. |
paul@682 | 24 | |
paul@682 | 25 | for n, (question, response_question) in enumerate(map(None, questions.xpath(question_path), responses.xpath(question_path))): |
paul@682 | 26 | |
paul@682 | 27 | # Each response container can contain a number of responses. |
paul@682 | 28 | |
paul@682 | 29 | for response in response_question.xpath("response"): |
paul@682 | 30 | |
paul@682 | 31 | # Get the question number (starting from 1) and the selected response, |
paul@682 | 32 | # if any. |
paul@682 | 33 | |
paul@682 | 34 | qn = n + 1 |
paul@682 | 35 | selected = response.getAttribute("selected") |
paul@682 | 36 | if selected is None: |
paul@682 | 37 | continue |
paul@682 | 38 | |
paul@682 | 39 | # Determine the selected response and whether a textual answer is |
paul@682 | 40 | # expected. |
paul@682 | 41 | |
paul@682 | 42 | selected = int(selected) |
paul@682 | 43 | textual_answer = bool(question.xpath("choice[position() = %d]/response-type[@value != 'choice']" % selected)) |
paul@682 | 44 | |
paul@682 | 45 | # Collect the answer. |
paul@682 | 46 | |
paul@682 | 47 | if not answers.has_key(qn): |
paul@682 | 48 | answers[qn] = {} |
paul@682 | 49 | if not answers[qn].has_key(selected): |
paul@682 | 50 | if textual_answer: |
paul@682 | 51 | answers[qn][selected] = [] |
paul@682 | 52 | else: |
paul@682 | 53 | answers[qn][selected] = 0 |
paul@682 | 54 | |
paul@682 | 55 | # Either record counts or specific answers. |
paul@682 | 56 | |
paul@682 | 57 | if textual_answer: |
paul@682 | 58 | text = response.getAttribute("response-text") |
paul@682 | 59 | if text: |
paul@682 | 60 | answers[qn][selected].append(text) |
paul@682 | 61 | else: |
paul@682 | 62 | answers[qn][selected] += 1 |
paul@682 | 63 | |
paul@682 | 64 | if __name__ == "__main__": |
paul@682 | 65 | resource_dir = resources(__file__) |
paul@682 | 66 | responses_dir = os.path.join(os.getcwd(), "Responses") |
paul@682 | 67 | questions = libxml2dom.parse(os.path.join(resource_dir, "questions.xml")) |
paul@682 | 68 | answers = collect(questions, responses_dir) |
paul@682 | 69 | |
paul@682 | 70 | # Get the collected answers in order. |
paul@682 | 71 | |
paul@682 | 72 | items = answers.items() |
paul@682 | 73 | items.sort() |
paul@682 | 74 | |
paul@682 | 75 | # Visit each answer record... |
paul@682 | 76 | |
paul@682 | 77 | for qn, answers_for_question in items: |
paul@682 | 78 | question = questions.xpath(question_path + ("[position() = %d]" % qn))[0] |
paul@682 | 79 | print "Question %d: %s" % (qn, question.getAttribute("question-text").strip()) |
paul@682 | 80 | |
paul@682 | 81 | # Get the response details in order. |
paul@682 | 82 | |
paul@682 | 83 | items_for_question = answers_for_question.items() |
paul@682 | 84 | items_for_question.sort() |
paul@682 | 85 | |
paul@682 | 86 | # Visit each distinct kind of response. |
paul@682 | 87 | |
paul@682 | 88 | for selected, results in items_for_question: |
paul@682 | 89 | choice = question.xpath("choice[position() = %d]" % selected)[0] |
paul@682 | 90 | choice_text = choice.getAttribute("response-choice").strip() |
paul@682 | 91 | if choice_text: |
paul@682 | 92 | print " ", ("%s:" % choice_text), |
paul@682 | 93 | |
paul@682 | 94 | if isinstance(results, int): |
paul@682 | 95 | print results |
paul@682 | 96 | else: |
paul@682 | 97 | print |
paul@682 | 98 | sorted_results = results[:] |
paul@682 | 99 | sorted_results.sort() |
paul@682 | 100 | for result in sorted_results: |
paul@682 | 101 | print " ", result |
paul@682 | 102 | |
paul@682 | 103 | print |
paul@682 | 104 | |
paul@682 | 105 | # vim: tabstop=4 expandtab shiftwidth=4 |