Mercurial > genshi > mirror
diff markup/core.py @ 17:74cc70129d04 trunk
Refactoring to address #6: all match templates are now processed by a single filter, which means that match templates added by included templates are properly applied. A side effect of this refactoring is that `Context` objects may not be reused across multiple template processing runs.
Also, output filters are now applied in the `Stream.serialize()` method instead of by the `Template.generate()` method, which just makes more sense.
author | cmlenz |
---|---|
date | Sun, 18 Jun 2006 22:33:33 +0000 |
parents | f77f7a91aa46 |
children | 5420cfe42d36 |
line wrap: on
line diff
--- a/markup/core.py +++ b/markup/core.py @@ -20,17 +20,9 @@ __all__ = ['Stream', 'Markup', 'escape', 'unescape', 'Namespace', 'QName'] -class StreamEventKind(object): +class StreamEventKind(str): """A kind of event on an XML stream.""" - __slots__ = ['name'] - - def __init__(self, name): - self.name = name - - def __repr__(self): - return self.name - class Stream(object): """Represents a stream of markup events. @@ -52,15 +44,15 @@ """ __slots__ = ['events'] - START = StreamEventKind('start') # a start tag - END = StreamEventKind('end') # an end tag - TEXT = StreamEventKind('text') # literal text - PROLOG = StreamEventKind('prolog') # XML prolog - DOCTYPE = StreamEventKind('doctype') # doctype declaration - START_NS = StreamEventKind('start-ns') # start namespace mapping - END_NS = StreamEventKind('end-ns') # end namespace mapping - PI = StreamEventKind('pi') # processing instruction - COMMENT = StreamEventKind('comment') # comment + START = StreamEventKind('START') # a start tag + END = StreamEventKind('END') # an end tag + TEXT = StreamEventKind('TEXT') # literal text + PROLOG = StreamEventKind('PROLOG') # XML prolog + DOCTYPE = StreamEventKind('DOCTYPE') # doctype declaration + START_NS = StreamEventKind('START-NS') # start namespace mapping + END_NS = StreamEventKind('END-NS') # end namespace mapping + PI = StreamEventKind('PI') # processing instruction + COMMENT = StreamEventKind('COMMENT') # comment def __init__(self, events): """Initialize the stream with a sequence of markup events. @@ -72,7 +64,7 @@ def __iter__(self): return iter(self.events) - def render(self, method='xml', encoding='utf-8', **kwargs): + def render(self, method='xml', encoding='utf-8', filters=None, **kwargs): """Return a string representation of the stream. @param method: determines how the stream is serialized; can be either @@ -83,7 +75,8 @@ Any additional keyword arguments are passed to the serializer, and thus depend on the `method` parameter value. """ - output = u''.join(list(self.serialize(method=method, **kwargs))) + generator = self.serialize(method=method, filters=filters, **kwargs) + output = u''.join(list(generator)) if encoding is not None: return output.encode(encoding) return output @@ -95,10 +88,9 @@ @param path: a string containing the XPath expression """ from markup.path import Path - path = Path(path) - return path.select(self) + return Path(path).select(self) - def serialize(self, method='xml', **kwargs): + def serialize(self, method='xml', filters=None, **kwargs): """Generate strings corresponding to a specific serialization of the stream. @@ -109,6 +101,7 @@ @param method: determines how the stream is serialized; can be either 'xml' or 'html', or a custom `Serializer` subclass """ + from markup.filters import WhitespaceFilter from markup import output cls = method if isinstance(method, basestring): @@ -117,7 +110,14 @@ else: assert issubclass(cls, serializers.Serializer) serializer = cls(**kwargs) - return serializer.serialize(self) + + stream = self + if filters is None: + filters = [WhitespaceFilter()] + for filter_ in filters: + stream = filter_(iter(stream)) + + return serializer.serialize(stream) def __str__(self): return self.render() @@ -176,6 +176,9 @@ def __mul__(self, num): return Markup(unicode(self) * num) + def __repr__(self): + return '<%s "%s">' % (self.__class__.__name__, self) + def join(self, seq): return Markup(unicode(self).join([Markup.escape(item) for item in seq])) @@ -184,7 +187,8 @@ replaced by the equivalent UTF-8 characters. If the `keepxmlentities` parameter is provided and evaluates to `True`, - the core XML entities (&, ', >, < and "). + the core XML entities (&, ', >, < and ") are not + stripped. """ def _replace_entity(match): if match.group(1): # numeric entity @@ -255,9 +259,8 @@ def sanitize(self): from markup.filters import HTMLSanitizer from markup.input import HTMLParser - sanitize = HTMLSanitizer() - text = self.stripentities(keepxmlentities=True) - return Stream(sanitize(HTMLParser(StringIO(text)), None)) + text = StringIO(self.stripentities(keepxmlentities=True)) + return Stream(HTMLSanitizer()(HTMLParser(text))) escape = Markup.escape