# HG changeset patch # User cmlenz # Date 1212266923 0 # Node ID 1447d40df660dca2123b1dd833394589c5131951 # Parent 0b36975cb24169a460f859b09232bb23cee96169 * Add XHTML 1.1 doctype (closes #228). * Add option to include the XML decl in the output when serializing to XHTML. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -79,6 +79,9 @@ base class (ticket #211). * The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir` (ticket #207). + * The `XHTMLSerializer` now has a `drop_xml_decl` option that defaults to + `True`. Setting it to `False` will cause any XML decl in the serialized + stream to be included in the output as it would for XML serialization. Version 0.4.4 diff --git a/doc/streams.txt b/doc/streams.txt --- a/doc/streams.txt +++ b/doc/streams.txt @@ -220,6 +220,13 @@ (This option is not available for serialization to HTML or plain text.) +``drop_xml_decl`` + Whether to remove the XML declaration (the ```` part at the + beginning of a document) when serializing. This defaults to ``True`` as an + XML declaration throws some older browsers into "Quirks" rendering mode. + + (This option is only available for serialization to XHTML.) + Using XPath diff --git a/genshi/output.py b/genshi/output.py --- a/genshi/output.py +++ b/genshi/output.py @@ -114,6 +114,11 @@ ) XHTML = XHTML_STRICT + XHTML11 = ( + 'html', '-//W3C//DTD XHTML 1.1//EN', + 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd' + ) + SVG_FULL = ( 'svg', '-//W3C//DTD SVG 1.1//EN', 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' @@ -140,6 +145,7 @@ * "xhtml" or "xhtml-strict" for the XHTML 1.0 strict DTD * "xhtml-transitional" for the XHTML 1.0 transitional DTD * "xhtml-frameset" for the XHTML 1.0 frameset DTD + * "xhtml11" for the XHTML 1.1 DTD * "svg" or "svg-full" for the SVG 1.1 DTD * "svg-basic" for the SVG Basic 1.1 DTD * "svg-tiny" for the SVG Tiny 1.1 DTD @@ -157,6 +163,7 @@ 'xhtml': cls.XHTML, 'xhtml-strict': cls.XHTML_STRICT, 'xhtml-transitional': cls.XHTML_TRANSITIONAL, 'xhtml-frameset': cls.XHTML_FRAMESET, + 'xhtml11': cls.XHTML11, 'svg': cls.SVG, 'svg-full': cls.SVG_FULL, 'svg-basic': cls.SVG_BASIC, 'svg-tiny': cls.SVG_TINY @@ -280,7 +287,7 @@ ]) def __init__(self, doctype=None, strip_whitespace=True, - namespace_prefixes=None): + namespace_prefixes=None, drop_xml_decl=True): super(XHTMLSerializer, self).__init__(doctype, False) self.filters = [EmptyTagFilter()] if strip_whitespace: @@ -290,11 +297,13 @@ self.filters.append(NamespaceFlattener(prefixes=namespace_prefixes)) if doctype: self.filters.append(DocTypeInserter(doctype)) + self.drop_xml_decl = drop_xml_decl def __call__(self, stream): boolean_attrs = self._BOOLEAN_ATTRS empty_elems = self._EMPTY_ELEMS - have_doctype = False + drop_xml_decl = self.drop_xml_decl + have_decl = have_doctype = False in_cdata = False for filter_ in self.filters: @@ -346,6 +355,18 @@ yield Markup(u''.join(buf)) % filter(None, data) have_doctype = True + elif kind is XML_DECL and not have_decl and not drop_xml_decl: + version, encoding, standalone = data + buf = ['\n') + yield Markup(u''.join(buf)) + have_decl = True + elif kind is START_CDATA: yield Markup('\n' @@ -203,6 +203,24 @@ class XHTMLSerializerTestCase(unittest.TestCase): + def test_xml_decl_dropped(self): + stream = Stream([(Stream.XML_DECL, ('1.0', None, -1), (None, -1, -1))]) + output = stream.render(XHTMLSerializer, doctype='xhtml') + self.assertEqual('\n', + output) + + def test_xml_decl_included(self): + stream = Stream([(Stream.XML_DECL, ('1.0', None, -1), (None, -1, -1))]) + output = stream.render(XHTMLSerializer, doctype='xhtml', + drop_xml_decl=False) + self.assertEqual('\n' + '\n', + output) + def test_xml_lang(self): text = '

English text

' output = XML(text).render(XHTMLSerializer)