-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.py
101 lines (79 loc) · 3.36 KB
/
util.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
#!/usr/bin/env python
import re
import datetime
from zoneinfo import ZoneInfo
import lxml
import lxml.etree
from pyopenmensa.feed import LazyBuilder
__all__ = ['xml_escape', 'xml_remove_invalid_chars', 'StyledLazyBuilder',
'now_local', 'xml_str_param', 'meta_from_xsl', 'weekdays_map']
default_style_sheets = ('https://cdn.jsdelivr.net/npm/om-style@1.0.0/basic.css',
'https://cdn.jsdelivr.net/npm/om-style@1.0.0/lightgreen.css')
def xml_escape(s, escape_double_quotes=False):
s = str(s).replace('&', '&') # amp first!
s = s.replace('>', '>')
s = s.replace('<', '<')
if escape_double_quotes:
s = s.replace('"', '"')
return s
def xml_remove_invalid_chars(s):
# https://www.w3.org/TR/xml/#char32
restricted_chars = re.compile(
r'[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]')
return restricted_chars.sub('', s)
class StyledLazyBuilder(LazyBuilder):
def toXMLFeed(self, styles=default_style_sheets):
feed = self.toXML()
xml_header = '<?xml version="1.0" encoding="UTF-8"?>\n'
if styles:
for style in styles:
xml_header += '<?xml-stylesheet href="' + \
xml_escape(style, True) + '" type="text/css"?>\n'
return xml_remove_invalid_chars(xml_header + feed.toprettyxml(indent=' '))
def now_local():
berlin = ZoneInfo('Europe/Berlin')
now = datetime.datetime.now(tz=berlin)
return now
def xml_str_param(s):
return lxml.etree.XSLT.strparam(str(s))
def meta_from_xsl(file_name, data):
"""Generate an openmensa XML meta feed using XSLT"""
if "times" in data:
opening_times = {}
pattern = re.compile(
r"([A-Z][a-z])(\s*-\s*([A-Z][a-z]))?\s*(\d{1,2}):(\d{2})\s*[-–]\s*(\d{1,2}):(\d{2})(?:\s*Uhr)?", flags=re.IGNORECASE)
m = re.findall(pattern, data["times"])
for result in m:
from_day, _, to_day, from_time_hours, from_time_minutes, to_time_hours, to_time_minutes = result
opening_times[from_day] = "%02d:%02d-%02d:%02d" % (
int(from_time_hours), int(from_time_minutes), int(to_time_hours), int(to_time_minutes))
if to_day:
select = False
for short, long in weekdays_map:
if short == from_day:
select = True
elif select:
opening_times[short] = "%02d:%02d-%02d:%02d" % (
int(from_time_hours), int(from_time_minutes), int(to_time_hours), int(to_time_minutes))
if short == to_day:
select = False
for short, long in weekdays_map:
if short in opening_times:
data[long] = xml_str_param(opening_times[short])
data["times"] = xml_str_param(True)
# Generate xml
xslt_tree = lxml.etree.parse(file_name)
xslt = lxml.etree.XSLT(xslt_tree)
return lxml.etree.tostring(xslt(lxml.etree.Element("foobar"), **data),
pretty_print=True,
xml_declaration=True,
encoding="utf-8").decode("utf-8")
weekdays_map = [
("Mo", "monday"),
("Tu", "tuesday"),
("We", "wednesday"),
("Th", "thursday"),
("Fr", "friday"),
("Sa", "saturday"),
("Su", "sunday")
]