Textbook browser
This commit is contained in:
@@ -115,7 +115,7 @@ class LoncapaModule(XModule):
|
|||||||
|
|
||||||
dom2 = etree.fromstring(xml)
|
dom2 = etree.fromstring(xml)
|
||||||
|
|
||||||
self.explanation=content_parser.item(dom2.xpath('/problem/@explain'))
|
self.explanation=content_parser.item(dom2.xpath('/problem/@explain'), default="closed")
|
||||||
self.explain_available=content_parser.item(dom2.xpath('/problem/@explain_available'))
|
self.explain_available=content_parser.item(dom2.xpath('/problem/@explain_available'))
|
||||||
|
|
||||||
self.due_date=content_parser.item(dom2.xpath('/problem/@due'))
|
self.due_date=content_parser.item(dom2.xpath('/problem/@due'))
|
||||||
|
|||||||
@@ -11,6 +11,30 @@ course XML file and the rest of the system.
|
|||||||
TODO: Shift everything from xml.dom.minidom to XPath (or XQuery)
|
TODO: Shift everything from xml.dom.minidom to XPath (or XQuery)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
def xpath(xml, query_string, **args):
|
||||||
|
''' Safe xpath query into an xml tree:
|
||||||
|
* xml is the tree.
|
||||||
|
* query_string is the query
|
||||||
|
* args are the parameters. Substitute for {params}. '''
|
||||||
|
doc = etree.fromstring(xml)
|
||||||
|
print type(doc)
|
||||||
|
def escape(x):
|
||||||
|
# TODO: This should escape the string. For now, we just assume it's made of valid characters.
|
||||||
|
# Couldn't figure out how to escape for lxml in a few quick Googles
|
||||||
|
valid_chars="".join(map(chr, range(ord('a'),ord('z')+1)+range(ord('A'),ord('Z')+1)+range(ord('0'), ord('9')+1)))+"_ "
|
||||||
|
for e in x:
|
||||||
|
if e not in valid_chars:
|
||||||
|
raise Exception("Invalid char in xpath expression. TODO: Escape")
|
||||||
|
return x
|
||||||
|
|
||||||
|
args=dict( ((k, escape(args[k])) for k in args) )
|
||||||
|
print args
|
||||||
|
results = doc.xpath(query_string.format(**args))
|
||||||
|
return results
|
||||||
|
|
||||||
|
if __name__=='__main__':
|
||||||
|
print xpath('<html><problem name="Bob"></problem></html>', '/{search}/problem[@name="{name}"]', search='html', name="Bob")
|
||||||
|
|
||||||
def item(l, default="", process=lambda x:x):
|
def item(l, default="", process=lambda x:x):
|
||||||
if len(l)==0:
|
if len(l)==0:
|
||||||
return default
|
return default
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ INSTALLED_APPS = (
|
|||||||
'django.contrib.humanize',
|
'django.contrib.humanize',
|
||||||
'static_template_view',
|
'static_template_view',
|
||||||
'textbook',
|
'textbook',
|
||||||
|
'staticbook',
|
||||||
# Uncomment the next line to enable the admin:
|
# Uncomment the next line to enable the admin:
|
||||||
# 'django.contrib.admin',
|
# 'django.contrib.admin',
|
||||||
# Uncomment the next line to enable admin documentation:
|
# Uncomment the next line to enable admin documentation:
|
||||||
|
|||||||
1
urls.py
1
urls.py
@@ -19,6 +19,7 @@ urlpatterns = patterns('',
|
|||||||
# url(r'^accounts/', include('registration.urls')),
|
# url(r'^accounts/', include('registration.urls')),
|
||||||
url(r'^t/(?P<template>[^/]*)$', 'static_template_view.views.index'),
|
url(r'^t/(?P<template>[^/]*)$', 'static_template_view.views.index'),
|
||||||
url(r'^textbook/(?P<filename>[^/]*)$', 'textbook.views.index'),
|
url(r'^textbook/(?P<filename>[^/]*)$', 'textbook.views.index'),
|
||||||
|
url(r'^book/(?P<page>[^/]*)$', 'staticbook.views.index'),
|
||||||
url(r'^logout$', 'auth.views.logout_user'),
|
url(r'^logout$', 'auth.views.logout_user'),
|
||||||
url(r'^login$', 'auth.views.login_user'),
|
url(r'^login$', 'auth.views.login_user'),
|
||||||
url(r'^login/(?P<error>[^/]*)$', 'auth.views.login_user'),
|
url(r'^login/(?P<error>[^/]*)$', 'auth.views.login_user'),
|
||||||
|
|||||||
Reference in New Issue
Block a user