Mercurial > genshi > mirror
diff markup/output.py @ 143:3d4c214c979a trunk
CDATA sections in XML input now appear as CDATA sections in the output. This should address the problem with escaping the contents of `<style>` and `<script>` elements, which would only get interpreted correctly if the output was served as `application/xhtml+xml`. Closes #24.
author | cmlenz |
---|---|
date | Fri, 11 Aug 2006 14:08:13 +0000 |
parents | 520a5b7dd6d2 |
children | 47bbd9d2a5af |
line wrap: on
line diff
--- a/markup/output.py +++ b/markup/output.py @@ -23,7 +23,8 @@ import re from markup.core import escape, Markup, Namespace, QName, XML_NAMESPACE -from markup.core import DOCTYPE, START, END, START_NS, END_NS, TEXT, COMMENT, PI +from markup.core import DOCTYPE, START, END, START_NS, END_NS, TEXT, \ + START_CDATA, END_CDATA, PI, COMMENT __all__ = ['Serializer', 'XMLSerializer', 'HTMLSerializer'] @@ -72,9 +73,10 @@ self.filters.append(WhitespaceFilter(self._PRESERVE_SPACE)) def __call__(self, stream): - have_doctype = False ns_attrib = [] ns_mapping = {XML_NAMESPACE.uri: 'xml'} + have_doctype = False + in_cdata = False stream = chain(self.preamble, stream) for filter_ in self.filters: @@ -125,7 +127,10 @@ yield Markup('</%s>' % tagname) elif kind is TEXT: - yield escape(data, quotes=False) + if in_cdata: + yield data + else: + yield escape(data, quotes=False) elif kind is COMMENT: yield Markup('<!--%s-->' % data) @@ -152,6 +157,14 @@ else: ns_attrib.append((QName('xmlns:%s' % prefix), uri)) + elif kind is START_CDATA: + yield Markup('<![CDATA[') + in_cdata = True + + elif kind is END_CDATA: + yield Markup(']]>') + in_cdata = False + elif kind is PI: yield Markup('<?%s %s?>' % data) @@ -182,6 +195,7 @@ boolean_attrs = self._BOOLEAN_ATTRS empty_elems = self._EMPTY_ELEMS have_doctype = False + in_cdata = False stream = chain(self.preamble, stream) for filter_ in self.filters: @@ -240,7 +254,10 @@ yield Markup('</%s>' % tagname) elif kind is TEXT: - yield escape(data, quotes=False) + if in_cdata: + yield data + else: + yield escape(data, quotes=False) elif kind is COMMENT: yield Markup('<!--%s-->' % data) @@ -267,6 +284,14 @@ else: ns_attrib.append((QName('xmlns:%s' % prefix), uri)) + elif kind is START_CDATA: + yield Markup('<![CDATA[') + in_cdata = True + + elif kind is END_CDATA: + yield Markup(']]>') + in_cdata = False + elif kind is PI: yield Markup('<?%s %s?>' % data) @@ -294,7 +319,7 @@ super(HTMLSerializer, self).__init__(doctype, False) if strip_whitespace: self.filters.append(WhitespaceFilter(self._PRESERVE_SPACE, - self._NOESCAPE_ELEMS)) + self._NOESCAPE_ELEMS, True)) def __call__(self, stream): namespace = self.NAMESPACE @@ -382,7 +407,7 @@ _LINE_COLLAPSE = re.compile('\n{2,}') _XML_SPACE = XML_NAMESPACE['space'] - def __init__(self, preserve=None, noescape=None): + def __init__(self, preserve=None, noescape=None, escape_cdata=False): """Initialize the filter. @param preserve: a set or sequence of tag names for which white-space @@ -399,6 +424,7 @@ if noescape is None: noescape = [] self.noescape = frozenset(noescape) + self.escape_cdata = escape_cdata def __call__(self, stream, ctxt=None): trim_trailing_space = self._TRAILING_SPACE.sub @@ -409,6 +435,7 @@ preserve = False noescape_elems = self.noescape noescape = False + escape_cdata = self.escape_cdata textbuf = [] push_text = textbuf.append @@ -441,6 +468,12 @@ elif kind is END: preserve = noescape = False + elif kind is START_CDATA and not escape_cdata: + noescape = True + + elif kind is END_CDATA and not escape_cdata: + noescape = False + if kind: yield kind, data, pos