Attachment 'OPML.py'
Download 1 # Released under the GNU Lesser General Public License, v2.1 or later
2 # Copyright (c) 2002 Juri Pakaste <[email protected]>
3 # $Id: OPML.py,v 1.5 2002/10/17 21:14:49 juri Exp $
4 # Fixed some bugs by limodou 2005/12/22
5
6 from xml.sax import make_parser, handler
7 from xml.sax.handler import feature_namespaces
8 from xml.sax.saxutils import XMLGenerator
9 from xml.sax.xmlreader import AttributesImpl
10 import sys
11
12 class OPML(dict):
13 def __init__(self):
14 self.outlines = []
15
16 def output(self, stream = sys.stdout):
17 xg = XMLGenerator(stream)
18 def elemWithContent(name, content):
19 xg.startElement(name, AttributesImpl({}))
20 if content is not None:
21 xg.characters(content)
22 xg.endElement(name)
23 xg.startElement("opml", AttributesImpl({'version': '1.1'}))
24 xg.startElement("head", AttributesImpl({}))
25 for key in ('title', 'dateCreated', 'dateModified', 'ownerName',
26 'ownerEmail', 'expansionState', 'vertScrollState',
27 'windowTop', 'windowBotton', 'windowRight', 'windowLeft'):
28 if self.has_key(key) and self[key] != "":
29 elemWithContent(key, self[key])
30 xg.endElement("head")
31 xg.startElement("body", AttributesImpl({}))
32 for o in self.outlines:
33 o.output(xg)
34 xg.endElement("body")
35 xg.endElement("opml")
36
37 class Outline(dict):
38 __slots__ = ('_children')
39
40 def __init__(self):
41 self._children = []
42
43 def add_child(self, outline):
44 self._children.append(outline)
45
46 def get_children_iter(self):
47 return self.OIterator(self)
48
49 children = property(get_children_iter, None, None, "")
50
51 def output(self, xg):
52 xg.startElement("outline", AttributesImpl(self))
53 for c in self.children:
54 c.output(xg)
55 xg.endElement("outline")
56
57 class OIterator:
58 def __init__(self, o):
59 self._o = o
60 self._index = -1
61
62 def __iter__(self):
63 return self
64
65 def next(self):
66 self._index += 1
67 if self._index < len(self._o._children):
68 return self._o._children[self._index]
69 else:
70 raise StopIteration
71
72 class OutlineList:
73 def __init__(self):
74 self._roots = []
75 self._stack = []
76
77 def add_outline(self, outline):
78 if len(self._stack):
79 self._stack[-1].add_child(outline)
80 else:
81 self._roots.append(outline)
82 self._stack.append(outline)
83
84 def close_outline(self):
85 if len(self._stack):
86 del self._stack[-1]
87
88 def roots(self):
89 return self._roots
90
91 class OPMLHandler(handler.ContentHandler):
92 def __init__(self):
93 self._outlines = OutlineList()
94 self._opml = None
95 self._content = ""
96
97 def startElement(self, name, attrs):
98 if self._opml is None:
99 if name != 'opml':
100 raise ValueError, "This doesn't look like OPML"
101 self._opml = OPML()
102 if name == 'outline':
103 o = Outline()
104 o.update(attrs)
105 self._outlines.add_outline(o)
106 self._content = ""
107
108 def endElement(self, name):
109 if name == 'outline':
110 self._outlines.close_outline()
111 return
112 if name == 'opml':
113 self._opml.outlines = self._outlines.roots()
114 return
115 for key in ('title', 'dateCreated', 'dateModified', 'ownerName',
116 'ownerEmail', 'expansionState', 'vertScrollState',
117 'windowTop', 'windowBotton', 'windowRight', 'windowLeft'):
118 if name == key:
119 self._opml[key] = self._content
120 return
121
122 def characters(self, ch):
123 self._content += ch
124
125 def get_opml(self):
126 return self._opml
127
128 def parse(stream):
129 parser = make_parser()
130 parser.setFeature(feature_namespaces, 0)
131 handler = OPMLHandler()
132 parser.setContentHandler(handler)
133
134 parser.parse(stream)
135 return handler.get_opml()
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.