changeset 729:be0b4a7b2fd4 trunk

* Add XHTML 1.1 doctype (closes #228). * Add option to include the XML decl in the output when serializing to XHTML.
author cmlenz
date Sat, 31 May 2008 20:48:43 +0000
parents c7badaa0be0c
children 5e9d250ad3ad
files ChangeLog doc/streams.txt genshi/output.py genshi/tests/output.py
diffstat 4 files changed, 52 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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 ``<?xml ?>`` 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
--- 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 = ['<?xml version="%s"' % version]
+                if encoding:
+                    buf.append(' encoding="%s"' % encoding)
+                if standalone != -1:
+                    standalone = standalone and 'yes' or 'no'
+                    buf.append(' standalone="%s"' % standalone)
+                buf.append('?>\n')
+                yield Markup(u''.join(buf))
+                have_decl = True
+
             elif kind is START_CDATA:
                 yield Markup('<![CDATA[')
                 in_cdata = True
--- a/genshi/tests/output.py
+++ b/genshi/tests/output.py
@@ -23,7 +23,7 @@
 
 class XMLSerializerTestCase(unittest.TestCase):
 
-    def test_xml_serialiser_with_decl(self):
+    def test_with_xml_decl(self):
         stream = Stream([(Stream.XML_DECL, ('1.0', None, -1), (None, -1, -1))])
         output = stream.render(XMLSerializer, doctype='xhtml')
         self.assertEqual('<?xml version="1.0"?>\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('<!DOCTYPE html PUBLIC '
+                         '"-//W3C//DTD XHTML 1.0 Strict//EN" '
+                         '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\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('<?xml version="1.0"?>\n'
+                         '<!DOCTYPE html PUBLIC '
+                         '"-//W3C//DTD XHTML 1.0 Strict//EN" '
+                         '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n',
+                         output)
+
     def test_xml_lang(self):
         text = '<p xml:lang="en">English text</p>'
         output = XML(text).render(XHTMLSerializer)
Copyright (C) 2012-2017 Edgewall Software