2 from xml
.etree
import ElementTree
as ET
5 class IceToTgd(object):
7 def use_xml_file(self
, filename
):
8 self
.tree
= ET
.parse(filename
)
10 self
.load_programmes()
12 def load_channels(self
):
15 {'lcn': ch
.findtext('lcn'),
16 'display-name': ch
.findtext('display-name')})
17 for ch
in self
.tree
.findall('channel')])
19 def load_programmes(self
):
21 return type(x
) is type([])
23 def extract_list_without_none(xml
, path
):
25 [y
.text
for y
in xml
.findall(path
)]
30 ({'title': p
.findtext('title'),
31 'sub-title': p
.findtext('sub-title'),
32 'desc': p
.findtext('desc'),
33 'categories': extract_list_without_none(p
, 'category'),
34 'channel': p
.get('channel'),
35 'rating': p
.findtext('rating/value'),
36 'date': p
.findtext('date'),
37 'subtitles': p
.findtext('subtitles'),
38 'directors': extract_list_without_none(p
, 'credits/director'),
39 'actors': extract_list_without_none(p
, 'credits/actor'),
40 'previously-shown': None if p
.find('previously-shown') is None \
41 else p
.find('previously-shown').get('start', ''),
42 'start': timestamp_from_xmltv_time(p
.get('start')),
43 'stop': timestamp_from_xmltv_time(p
.get('stop'))},
44 lambda k
,v
: v
is not None and (not listp(v
) or v
))
45 for p
in self
.tree
.findall('programme')]
47 def tgd_channel(self
, programme
):
48 return self
.channels
[programme
['channel']]['lcn']
50 def tgd_title(self
, programme
):
51 title
= programme
['title']
52 if 'date' in programme
:
53 title
+= ' (%s)' % programme
['date']
56 def tgd_short_description(self
, programme
):
57 sub_title
= programme
.get('sub-title', '')
59 if 'categories' in programme
:
61 '/'.join(programme
['categories']) + ']'
62 return ' '.join([sub_title
, categories
])
64 def tgd_description(self
, programme
):
65 desc
= programme
.get('desc', '')
66 if 'subtitles' in programme
:
67 desc
+= ' [Subtitles]'
68 if 'previously-shown' in programme
:
69 datestr
= programme
['previously-shown']
73 date
= datetime
.date(int(datestr
[0:4]), int(datestr
[4:6]), int(datestr
[6:8]))
74 out
= date
.strftime('%x')
75 desc
+= ' [Repeat, last shown ' + out
+ ']'
76 cast
= self
.tgd_cast_text(programme
)
78 desc
+= ' ' + cast
+ '.'
79 directors
= self
.tgd_director_text(programme
)
80 if directors
is not None:
81 desc
+= ' Dir. ' + directors
+ '.'
84 def tgd_rating(self
, programme
):
85 return programme
.get('rating', 'X')
87 def tgd_director_text(self
, programme
):
88 if 'directors' in programme
:
89 return ', '.join(programme
['directors'])
93 def tgd_cast_text(self
, programme
):
94 if 'actors' in programme
:
95 return ', '.join(programme
['actors'])
99 def programme_to_tgd(self
, programme
):
100 tgd_channel
= self
.tgd_channel(programme
)
101 tgd_start
= tgd_time_from_timestamp(programme
['start'])
102 duration
= programme
['stop'] - programme
['start']
103 tgd_duration
= tgd_duration_from_timedelta(duration
)
106 line
= '\t'.join([str_or_empty(x
)
107 for x
in [tgd_channel
,
110 self
.tgd_title(programme
),
111 self
.tgd_short_description(programme
),
112 self
.tgd_description(programme
),
113 self
.tgd_rating(programme
),
117 def timestamp_from_xmltv_time(timestr
):
118 return datetime
.datetime
.strptime(timestr
, '%Y%m%d%H%M%S +0000')
120 def tgd_time_from_timestamp(timestamp
):
121 t
= timestamp_as_localtime(timestamp
)
122 return t
.strftime('%Y/%m/%d %H:%M')
124 def timestamp_as_localtime(timestamp
):
126 return timestamp
+ datetime
.timedelta(0, 36000 + 3600, 0)
128 def tgd_duration_from_timedelta(duration
):
129 return str(duration
.seconds
/ 60)
132 return s
if s
is not None else ''
134 def filter_dict(d
, predicate
):
135 return dict([(k
,v
) for (k
,v
) in d
.iteritems() if predicate(k
,v
)])
137 def tgd_filename_from_programme(programme
):
138 t
= timestamp_as_localtime(programme
['start'])
139 return t
.strftime('%Y%m%d.tgd')
141 sd_channels
= ('2','22','3','7','9','10','23','32','72','99','12')
143 if __name__
=='__main__':
144 filename
= 'iceguide.xml'
146 parser
.use_xml_file(filename
)
147 current_tgd_filename
= None
148 current_tgd_file
= None
149 for p
in parser
.programmes
:
150 if parser
.tgd_channel(p
) in sd_channels
:
151 new_tgd_filename
= tgd_filename_from_programme(p
)
152 if new_tgd_filename
!= current_tgd_filename
:
153 current_tgd_file
= open('out/' + new_tgd_filename
, 'a')
155 line
= parser
.programme_to_tgd(p
).encode('UTF-8')
157 print 'data: "%s"' % p
159 current_tgd_file
.write(line
+ '\r\n')