-
Notifications
You must be signed in to change notification settings - Fork 1
/
toIMS.py
161 lines (141 loc) · 6.79 KB
/
toIMS.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import json
import os
import sys
import zipfile
import random
from lxml import etree
from lxml import html
from pprint import pprint
from yattag import indent
from yattag import Doc
FILETYPES = {
'weblink' : 'imswl_xmlv1p1',
'discussions' : 'imsdt_xmlv1p1',
'auto-evaluation' : 'imsqti_xmlv1p2/imscc_xmlv1p1/assessment',
'webcontent' : 'webcontent',
}
def usage():
str = """
Usage:
exporte les fichiers depuis l'arborescence git pour les comprimer dans une archive .imscc.
toIMS config_filein fileout
"""
print (str)
exit(1)
def replaceLink(link):
""" Replace __BASE__ in urls with base given un config file toIMSconfig.json """
return link.replace("__BASE__/", '')
def generateIMSManifest(data):
""" parse data from config file 'toIMSconfig.json' and recreate imsmanifest.xml """
# create magic yattag triple
doc, tag, text = Doc().tagtext()
# open tag 'manifest' with default content:
doc.asis('<?xml version="1.0" encoding="UTF-8"?><manifest xmlns="http://www.imsglobal.org/xsd/imsccv1p1/imscp_v1p1" xmlns:lomimscc="http://ltsc.ieee.org/xsd/imsccv1p1/LOM/manifest" xmlns:lom="http://ltsc.ieee.org/xsd/imsccv1p1/LOM/resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" identifier="M_3E1AEC6D" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsccv1p1/imscp_v1p1 http://www.imsglobal.org/profile/cc/ccv1p1/ccv1p1_imscp_v1p2_v1p0.xsd http://ltsc.ieee.org/xsd/imsccv1p1/LOM/manifest http://www.imsglobal.org/profile/cc/ccv1p1/LOM/ccv1p1_lommanifest_v1p0.xsd http://ltsc.ieee.org/xsd/imsccv1p1/LOM/resource http://www.imsglobal.org/profile/cc/ccv1p1/LOM/ccv1p1_lomresource_v1p0.xsd">')
# Print metadata
with tag('metadata'):
with tag('schema'):
text('IMS Common Cartridge')
with tag('schemaversion'):
text('1.1.0')
with tag('lomimscc:lom'):
with tag('lomimscc:general'):
with tag('lomimscc:title'):
with tag('lomimscc:string', language=data["lom_metadata"]["language"]):
text(data["lom_metadata"]["title"])
with tag('lomimscc:language'):
text(data["lom_metadata"]["language"])
with tag('lomimscc:description'):
doc.stag('lomimscc:string', language=data["lom_metadata"]["language"])
with tag('lomimscc:identifier'):
with tag('lomimscc:catalog'):
text('category')
with tag('lomimscc:entry'):
text(data["lom_metadata"]["category"])
# Print organization
resources = []
with tag('organizations'):
with tag('organization', identifier="organization0", structure='rooted-hierarchy'):
with tag('item', identifier='root'):
for idA, section in enumerate(data["sections"]):
section_id = "sec_"+(str(idA))
with tag('item', identifier=section_id):
with tag('title'):
text(str(idA))
for idB, subsection in enumerate(data["sections"][idA]["subsections"]):
href = data["sections"][idA]["subsections"][idB]["source_file"]
filename = href.rsplit('/',1)[1]
resources.append(filename)
with tag('item', identifier=("subsec_"+str(idA)+"_"+str(idB)), identifierref=("doc_"+str(idA)+"_"+str(idB))):
with tag('title'):
text(data["sections"][idA]["subsections"][idB]["title"])
# Print resources
with tag('resources'):
# retrieve images and add dependency when needed
doc.asis("<!-- Images -->")
images = {}
for idx, filename in enumerate(os.listdir(os.getcwd()+'/img')):
if filename in resources:
pass # avoid duplicating resources
else:
doc_id = "img_"+str(idx)
images[filename] = doc_id # store img id for further reference
with tag('resource', identifier=doc_id, type="webcontent", href="img/"+filename):
doc.stag('file', href="img/"+filename)
doc.asis("<!-- Webcontent -->")
for idA, section in enumerate(data["sections"]):
for idB, subsection in enumerate(data["sections"][idA]["subsections"]):
doc_id = "doc_"+str(idA)+"_"+str(idB)
file_type = FILETYPES[data["sections"][idA]["subsections"][idB]["type"]]
href = data["sections"][idA]["subsections"][idB]["source_file"]
with tag('resource', identifier=doc_id, type=file_type, href=href):
doc.stag('file', href=href)
# add dependency if needed (html only)
if file_type == "webcontent":
html_doc = html.parse(href)
img_sources = html_doc.xpath('//@src')
for img in img_sources:
img = img.rsplit('/', 1)[1]
if img in images:
# add dependency
doc.stag('dependency', identifierref=images[img])
# rewrite absolute href links
# body = html_doc.find('body')
# body.rewrite_links(replaceLink)
# f = open(href,"wb")
# f.write(html.tostring(body))
# f.close()
doc.asis("</manifest>")
imsfile = open('imsmanifest.xml', 'w')
imsfile.write(indent(doc.getvalue()))
imsfile.close()
return True
def main(argv):
""" toIMS is a utility to help building imscc archives for exporting curent material to Moodle """
if len(sys.argv) != 3:
usage()
filein = sys.argv[1]
fileout = sys.argv[2]
# add .zip if not there
if fileout.rsplit('.', 1)[1] != 'zip':
fileout += '.zip'
# load data from filin
with open(filein, encoding='utf-8') as data_file:
data = json.load(data_file)
# parse data and generate imsmanifest.xml
generateIMSManifest(data)
print (" imsmanifest.xml saved. Compressing archive in %s " % (os.getcwd()))
# Compress relevant files
zipf = zipfile.ZipFile(fileout, 'w')
zipf.write(os.getcwd()+'/imsmanifest.xml')
for dir_name in data['directories_to_ims']:
for file in os.listdir(dir_name):
filepath = os.path.join(os.getcwd(), dir_name)
filepath = os.path.join(filepath, file)
print (" Adding %s to archive " % (filepath))
zipf.write(filepath)
zipf.close()
############### main ################
if __name__ == "__main__":
main(sys.argv)