2
from xml.sax import saxutils, make_parser
3
from xml.sax.handler import feature_namespaces, ContentHandler
7
##############################################################################
11
##############################################################################
13
class memaid_XML_Importer(ContentHandler):
15
def __init__(self, default_cat=None, reset_learning_data=False):
16
self.reading, self.text = {}, {}
18
self.reading["cat"] = False
19
self.reading["Q"] = False
20
self.reading["A"] = False
22
self.default_cat = default_cat
23
self.reset_learning_data = reset_learning_data
25
self.imported_cards = []
27
def to_bool(self, string):
33
def startElement(self, name, attrs):
34
global import_time_of_start
37
if attrs.get("time_of_start"):
38
import_time_of_start \
39
= StartTime(long(attrs.get("time_of_start")))
41
import_time_of_start = time_of_start
46
self.card.id = long(attrs.get("id"))
47
self.card.grade = int(attrs.get("gr"))
48
self.card.next_rep = int(attrs.get("tm_t_rpt"))
49
self.card.ret_reps = int(attrs.get("rp"))
50
interval = int(attrs.get("ivl"))
51
self.card.last_rep = self.card.next_rep - interval
52
self.card.easiness = average_easiness()
54
elif name == "category":
55
self.active = self.to_bool(attrs.get("scheduled"))
57
self.reading[name] = True
60
def characters(self, ch):
61
for name in self.reading.keys():
62
if self.reading[name] == True:
65
def endElement(self, name):
67
self.reading[name] = False
71
cat_name = self.text["cat"]
72
self.card.cat = get_category_by_name(cat_name)
76
self.card.q = self.text["Q"]
80
self.card.a = self.text["A"]
87
if self.card.cat == None:
88
self.card.cat = self.default_cat
90
if self.reset_learning_data == True:
91
self.card.reset_learning_data()
92
self.card.easiness = average_easiness()
94
self.imported_cards.append(self.card)
96
elif name == "category":
98
name = self.text["name"]
100
ensure_category_exists(name)
101
get_category_by_name(name).active = self.active
105
# TODO: remove duplication over different XML formats
107
##############################################################################
111
# Note that we do not register separate file formats for Mnemosyne and
112
# Memaid XML. We're able to figure out the difference on our own and do not
113
# need to put this burden on the user.
115
##############################################################################
117
def import_XML(filename, default_cat, reset_learning_data=False):
120
# Determine if we import a Mnemosyne or a Memaid file.
129
f = file(unicode(filename).encode("latin"))
136
handler = XML_Importer(default_cat, reset_learning_data)
137
elif "smconv_pl" in l:
138
handler = smconv_XML_Importer(default_cat, reset_learning_data)
140
handler = memaid_XML_Importer(default_cat, reset_learning_data)
146
parser = make_parser()
147
parser.setFeature(feature_namespaces, 0)
148
parser.setContentHandler(handler)
151
# Use cStringIo to avoid a crash in sax when filename has unicode
153
s = file(filename).read()
154
f = cStringIO.StringIO(s)
157
raise XMLError(stack_trace=True)
159
# Calculate offset with current start date.
161
cur_start_date = time_of_start.time
162
imp_start_date = import_time_of_start.time
164
offset = long(round((cur_start_date - imp_start_date) / 60. / 60. / 24.))
168
if reset_learning_data == False:
169
if cur_start_date <= imp_start_date :
170
for card in handler.imported_cards:
171
card.last_rep += abs(offset)
172
card.next_rep += abs(offset)
174
time_of_start = StartTime(imp_start_date)
176
card.last_rep += abs(offset)
177
card.next_rep += abs(offset)
179
return handler.imported_cards