]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #5027: The standard `xml` namespace is now understood by
authorAntoine Pitrou <solipsis@pitrou.net>
Wed, 27 Oct 2010 18:33:30 +0000 (18:33 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Wed, 27 Oct 2010 18:33:30 +0000 (18:33 +0000)
xml.sax.saxutils.XMLGenerator as being bound to
http://www.w3.org/XML/1998/namespace.  Patch by Troy J. Farrell.

Lib/test/test_sax.py
Lib/xml/sax/saxutils.py
Misc/ACKS
Misc/NEWS

index 143ddf2940d828207c6956ae40b91f2a7bcb1db3..c4b211f6bf9a76ca123e52a1c833827bcb83cb69 100644 (file)
@@ -11,6 +11,7 @@ except SAXReaderNotAvailable:
 from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
                              XMLFilterBase
 from xml.sax.expatreader import create_parser
+from xml.sax.handler import feature_namespaces
 from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
 from io import StringIO
 from test.support import findfile, run_unittest
@@ -385,6 +386,60 @@ class XmlgenTest(unittest.TestCase):
         self.assertEquals(result.getvalue(),
             start+'<my:a xmlns:my="qux" b="c"/>')
 
+    def test_5027_1(self):
+        # The xml prefix (as in xml:lang below) is reserved and bound by
+        # definition to http://www.w3.org/XML/1998/namespace.  XMLGenerator had
+        # a bug whereby a KeyError is thrown because this namespace is missing
+        # from a dictionary.
+        #
+        # This test demonstrates the bug by parsing a document.
+        test_xml = StringIO(
+            '<?xml version="1.0"?>'
+            '<a:g1 xmlns:a="http://example.com/ns">'
+             '<a:g2 xml:lang="en">Hello</a:g2>'
+            '</a:g1>')
+
+        parser = make_parser()
+        parser.setFeature(feature_namespaces, True)
+        result = StringIO()
+        gen = XMLGenerator(result)
+        parser.setContentHandler(gen)
+        parser.parse(test_xml)
+
+        self.assertEquals(result.getvalue(),
+                          start + (
+                          '<a:g1 xmlns:a="http://example.com/ns">'
+                           '<a:g2 xml:lang="en">Hello</a:g2>'
+                          '</a:g1>'))
+
+    def test_5027_2(self):
+        # The xml prefix (as in xml:lang below) is reserved and bound by
+        # definition to http://www.w3.org/XML/1998/namespace.  XMLGenerator had
+        # a bug whereby a KeyError is thrown because this namespace is missing
+        # from a dictionary.
+        #
+        # This test demonstrates the bug by direct manipulation of the
+        # XMLGenerator.
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.startPrefixMapping('a', 'http://example.com/ns')
+        gen.startElementNS(('http://example.com/ns', 'g1'), 'g1', {})
+        lang_attr = {('http://www.w3.org/XML/1998/namespace', 'lang'): 'en'}
+        gen.startElementNS(('http://example.com/ns', 'g2'), 'g2', lang_attr)
+        gen.characters('Hello')
+        gen.endElementNS(('http://example.com/ns', 'g2'), 'g2')
+        gen.endElementNS(('http://example.com/ns', 'g1'), 'g1')
+        gen.endPrefixMapping('a')
+        gen.endDocument()
+
+        self.assertEquals(result.getvalue(),
+                          start + (
+                          '<a:g1 xmlns:a="http://example.com/ns">'
+                           '<a:g2 xml:lang="en">Hello</a:g2>'
+                          '</a:g1>'))
+
 
 class XMLFilterBaseTest(unittest.TestCase):
     def test_filter_basic(self):
index 46946fcf72e8775d27a15b067d972ac817bbeb55..625bc122ac2c21124ee9ac5f5526d7d2a9c7f5d8 100644 (file)
@@ -100,6 +100,12 @@ class XMLGenerator(handler.ContentHandler):
     def _qname(self, name):
         """Builds a qualified name from a (ns_url, localname) pair"""
         if name[0]:
+            # Per http://www.w3.org/XML/1998/namespace, The 'xml' prefix is
+            # bound by definition to http://www.w3.org/XML/1998/namespace.  It
+            # does not need to be declared and will not usually be found in
+            # self._current_context.
+            if 'http://www.w3.org/XML/1998/namespace' == name[0]:
+                return 'xml:' + name[1]
             # The name is in a non-empty namespace
             prefix = self._current_context[name[0]]
             if prefix:
index f5c672540db7d5ebc7e334dfeb946b1cc58ae7e9..d9e3f33fc7d08ed2d94a247c49f9e4cd7dc4724a 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -257,6 +257,7 @@ Greg Ewing
 Martijn Faassen
 Andreas Faerber
 Bill Fancher
+Troy J. Farrell
 Mark Favas
 Niels Ferguson
 Sebastian Fernandez
index d860a7abec837ef11aa465a24f20283cbf92c6ba..3f8d115cc9c592d698fa33f47da14e14cb9188f4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -51,6 +51,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #5027: The standard ``xml`` namespace is now understood by
+  xml.sax.saxutils.XMLGenerator as being bound to
+  http://www.w3.org/XML/1998/namespace.  Patch by Troy J. Farrell.
+
 - Issue #5975: Add csv.unix_dialect class.
 
 - Issue #7761: telnetlib.interact failures on Windows fixed.