comparison markup/output.py @ 26:3c1a022be04c trunk

* Split out the XPath tests into a separate `unittest`-based file. * Added many more docstrings. * Cleaned up the implementation of the XML/HTML parsers a bit. * The HTML parser now correctly handles minimized attributes. * Added `COPYING` and `README` files.
author cmlenz
date Wed, 28 Jun 2006 08:55:04 +0000
parents cc92d74ce9e5
children b4f78c05e5c9
comparison
equal deleted inserted replaced
25:e3be27f5bcf5 26:3c1a022be04c
19 frozenset 19 frozenset
20 except NameError: 20 except NameError:
21 from sets import ImmutableSet as frozenset 21 from sets import ImmutableSet as frozenset
22 22
23 from markup.core import Markup, Namespace, QName, Stream 23 from markup.core import Markup, Namespace, QName, Stream
24 from markup.filters import WhitespaceFilter
25 24
26 __all__ = ['Serializer', 'XMLSerializer', 'HTMLSerializer'] 25 __all__ = ['Serializer', 'XMLSerializer', 'HTMLSerializer']
27 26
28 27
29 class Serializer(object): 28 class Serializer(object):
30 """Base class for serializers.""" 29 """Base class for serializers."""
31 30
32 def serialize(self, stream): 31 def serialize(self, stream):
32 """Must be implemented by concrete subclasses to serialize the given
33 stream.
34
35 This method must be implemented as a generator, producing the
36 serialized output incrementally as unicode strings.
37 """
33 raise NotImplementedError 38 raise NotImplementedError
34 39
35 40
36 class XMLSerializer(Serializer): 41 class XMLSerializer(Serializer):
37 """Produces XML text from an event stream. 42 """Produces XML text from an event stream.
44 49
45 def serialize(self, stream): 50 def serialize(self, stream):
46 ns_attrib = [] 51 ns_attrib = []
47 ns_mapping = {} 52 ns_mapping = {}
48 53
49 stream = PushbackIterator(stream) 54 stream = _PushbackIterator(stream)
50 for kind, data, pos in stream: 55 for kind, data, pos in stream:
51 56
52 if kind is Stream.DOCTYPE: 57 if kind is Stream.DOCTYPE:
53 # FIXME: what if there's no system or public ID in the input? 58 # FIXME: what if there's no system or public ID in the input?
54 yield Markup('<!DOCTYPE %s "%s" "%s">\n' % data) 59 yield Markup('<!DOCTYPE %s "%s" "%s">\n' % data)
79 attrib.extend(ns_attrib) 84 attrib.extend(ns_attrib)
80 ns_attrib = [] 85 ns_attrib = []
81 for attr, value in attrib: 86 for attr, value in attrib:
82 attrname = attr.localname 87 attrname = attr.localname
83 if attr.namespace: 88 if attr.namespace:
84 try: 89 prefix = ns_mapping.get(attr.namespace)
85 prefix = ns_mapping[attr.namespace]
86 except KeyError:
87 # FIXME: synthesize a prefix for the attribute?
88 prefix = ''
89 if prefix: 90 if prefix:
90 attrname = prefix + ':' + attrname 91 attrname = prefix + ':' + attrname
91 buf.append(' %s="%s"' % (attrname, Markup.escape(value))) 92 buf.append(' %s="%s"' % (attrname, Markup.escape(value)))
92 93
93 kind, data, pos = stream.next() 94 kind, data, pos = stream.next()
101 102
102 elif kind is Stream.END: 103 elif kind is Stream.END:
103 tag = data 104 tag = data
104 tagname = tag.localname 105 tagname = tag.localname
105 if tag.namespace: 106 if tag.namespace:
106 try: 107 prefix = ns_mapping.get(tag.namespace)
107 prefix = ns_mapping[tag.namespace] 108 if prefix:
108 if prefix: 109 tagname = prefix + ':' + tag.localname
109 tagname = prefix + ':' + tag.localname
110 except KeyError:
111 pass
112 yield Markup('</%s>' % tagname) 110 yield Markup('</%s>' % tagname)
113 111
114 elif kind is Stream.TEXT: 112 elif kind is Stream.TEXT:
115 yield Markup.escape(data, quotes=False) 113 yield Markup.escape(data, quotes=False)
116 114
134 'nohref', 'noresize', 'noshade', 'nowrap']) 132 'nohref', 'noresize', 'noshade', 'nowrap'])
135 133
136 def serialize(self, stream): 134 def serialize(self, stream):
137 ns_mapping = {} 135 ns_mapping = {}
138 136
139 stream = PushbackIterator(stream) 137 stream = _PushbackIterator(stream)
140 for kind, data, pos in stream: 138 for kind, data, pos in stream:
141 139
142 if kind is Stream.DOCTYPE: 140 if kind is Stream.DOCTYPE:
143 yield Markup('<!DOCTYPE %s "%s" "%s">\n' % data) 141 yield Markup('<!DOCTYPE %s "%s" "%s">\n' % data)
144 142
177 175
178 elif kind is Stream.TEXT: 176 elif kind is Stream.TEXT:
179 yield Markup.escape(data, quotes=False) 177 yield Markup.escape(data, quotes=False)
180 178
181 179
182 class PushbackIterator(object): 180 class _PushbackIterator(object):
183 """A simple wrapper for iterators that allows pushing items back on the 181 """A simple wrapper for iterators that allows pushing items back on the
184 queue via the `pushback()` method. 182 queue via the `pushback()` method.
185 183
186 That can effectively be used to peek at the next item.""" 184 That can effectively be used to peek at the next item."""
187 __slots__ = ['iterable', 'buf'] 185 __slots__ = ['iterable', 'buf']
Copyright (C) 2012-2017 Edgewall Software