Index: genshi/tests/output.py
===================================================================
--- genshi/tests/output.py	(revision 928)
+++ genshi/tests/output.py	(working copy)
@@ -185,6 +185,112 @@
           <x:p xmlns:x="http://example.org/"/>
         </div>""", output)
 
+    def test_rebound_namespace(self):
+        stream = Stream([
+            (Stream.START_NS, ('a', 'http://example.org/'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/}div'), Attrs()), (None, -1, -1)),
+            (Stream.TEXT, '\n          ', (None, -1, -1)),
+            (Stream.START_NS, ('b', 'http://example.org/'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/}p'), Attrs()), (None, -1, -1)),
+            (Stream.END, QName('http://example.org/}p'), (None, -1, -1)),
+            (Stream.END_NS, 'b', (None, -1, -1)),
+            (Stream.TEXT, '\n        ', (None, -1, -1)),
+            (Stream.END, QName('http://example.org/}div'), (None, -1, -1)),
+            (Stream.END_NS, 'a', (None, -1, -1)),
+        ])
+        output = stream.render(XMLSerializer)
+        self.assertEqual("""<a:div xmlns:a="http://example.org/">
+          <a:p/>
+        </a:div>""", output)
+
+    def test_rebound_namespace_prefix(self):
+        stream = Stream([
+            (Stream.START_NS, ('x', 'http://example.org/a'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/a}div'), Attrs()), (None, -1, -1)),
+            (Stream.TEXT, '\n          ', (None, -1, -1)),
+            (Stream.START_NS, ('x', 'http://example.org/b'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/b}p'), Attrs()), (None, -1, -1)),
+            (Stream.END, QName('http://example.org/b}p'), (None, -1, -1)),
+            (Stream.END_NS, 'x', (None, -1, -1)),
+            (Stream.TEXT, '\n        ', (None, -1, -1)),
+            (Stream.END, QName('http://example.org/a}div'), (None, -1, -1)),
+            (Stream.END_NS, 'x', (None, -1, -1)),
+        ])
+        output = stream.render(XMLSerializer)
+        self.assertEqual("""<x:div xmlns:x="http://example.org/a">
+          <x:p xmlns:x="http://example.org/b"/>
+        </x:div>""", output)
+        
+    def test_rebound_namespace_with_rebound_namespace_prefix(self):
+        stream = Stream([
+            (Stream.START_NS, ('x', 'http://example.org/a'), (None, -1, -1)),
+            (Stream.START_NS, ('y', 'http://example.org/a'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/a}div'), Attrs()), (None, -1, -1)),
+            (Stream.TEXT, '\n          ', (None, -1, -1)),
+            (Stream.START_NS, ('x', 'http://example.org/b'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/b}p'), Attrs()), (None, -1, -1)),
+            (Stream.TEXT, '\n            ', (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/a}span'), Attrs()), (None, -1, -1)),
+            (Stream.END, QName('http://example.org/a}span'), (None, -1, -1)),
+            (Stream.TEXT, '\n          ', (None, -1, -1)),
+            (Stream.END, QName('http://example.org/b}p'), (None, -1, -1)),
+            (Stream.END_NS, 'x', (None, -1, -1)),
+            (Stream.TEXT, '\n        ', (None, -1, -1)),
+            (Stream.END, QName('http://example.org/a}div'), (None, -1, -1)),
+            (Stream.END_NS, 'y', (None, -1, -1)),
+            (Stream.END_NS, 'x', (None, -1, -1)),
+        ])
+        output = stream.render(XMLSerializer)
+        self.assertEqual("""<x:div xmlns:x="http://example.org/a">
+          <x:p xmlns:x="http://example.org/b">
+            <y:span xmlns:y="http://example.org/a"/>
+          </x:p>
+        </x:div>""", output)
+        
+    def test_multiple_bound_default_namespace_with_attribute(self):
+        stream = Stream([
+            (Stream.START_NS, ('', 'http://example.org/a'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/a}div'), Attrs()), (None, -1, -1)),
+            (Stream.TEXT, '\n          ', (None, -1, -1)),
+            (Stream.START_NS, ('a', 'http://example.org/a'), (None, -1, -1)),
+            (Stream.START_NS, ('b', 'http://example.org/b'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/a}div'), Attrs()), (None, -1, -1)),
+            (Stream.TEXT, '\n            ', (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/b}p'), Attrs([(QName('http://example.org/a}class'), 'name')])), (None, -1, -1)),
+            (Stream.END, QName('http://example.org/b}p'), (None, -1, -1)),
+            (Stream.TEXT, '\n          ', (None, -1, -1)),
+            (Stream.END, QName('http://example.org/a}div'), (None, -1, -1)),
+            (Stream.END_NS, 'b', (None, -1, -1)),
+            (Stream.END_NS, 'a', (None, -1, -1)),            
+            (Stream.TEXT, '\n        ', (None, -1, -1)),
+            (Stream.END, QName('http://example.org/a}div'), (None, -1, -1)),
+            (Stream.END_NS, '', (None, -1, -1)),
+        ])
+        output = stream.render(XMLSerializer)
+        self.assertEqual("""<div xmlns="http://example.org/a">
+          <div xmlns:a="http://example.org/a" xmlns:b="http://example.org/b">
+            <b:p a:class="name"/>
+          </div>
+        </div>""", output)
+    
+    def test_prefer_default_namespace(self):
+        stream = Stream([
+            (Stream.START_NS, ('a', 'http://example.org/'), (None, -1, -1)),
+            (Stream.START_NS, ('', 'http://example.org/'), (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/}div'), Attrs()), (None, -1, -1)),
+            (Stream.TEXT, '\n          ', (None, -1, -1)),
+            (Stream.START, (QName('http://example.org/}p'), Attrs()), (None, -1, -1)),
+            (Stream.END, QName('http://example.org/}p'), (None, -1, -1)),
+            (Stream.TEXT, '\n        ', (None, -1, -1)),
+            (Stream.END, QName('http://example.org/}div'), (None, -1, -1)),
+            (Stream.END_NS, '', (None, -1, -1)),
+            (Stream.END_NS, 'a', (None, -1, -1)),
+        ])
+        output = stream.render(XMLSerializer)
+        self.assertEqual("""<div xmlns:a="http://example.org/" xmlns="http://example.org/">
+          <p/>
+        </div>""", output)
+    
     def test_atom_with_xhtml(self):
         text = """<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
             <id>urn:uuid:c60843aa-0da8-4fa6-bbe5-98007bc6774e</id>
Index: genshi/output.py
===================================================================
--- genshi/output.py	(revision 928)
+++ genshi/output.py	(working copy)
@@ -17,6 +17,7 @@
 
 from itertools import chain
 import re
+import copy
 
 from genshi.core import escape, Attrs, Markup, Namespace, QName, StreamEventKind
 from genshi.core import START, END, TEXT, XML_DECL, DOCTYPE, START_NS, END_NS, \
@@ -573,10 +574,13 @@
             namespaces.setdefault(uri, []).append(prefix)
             prefixes.setdefault(prefix, []).append(uri)
 
+        active = [set(['xml'])]
         ns_attrs = []
-        _push_ns_attr = ns_attrs.append
         def _make_ns_attr(prefix, uri):
             return u'xmlns%s' % (prefix and ':%s' % prefix or ''), uri
+        def _push_ns_attr(prefix, uri):
+            ns_attrs.append(_make_ns_attr(prefix, uri))
+            active[-1].add(prefix)
 
         def _gen_prefix():
             val = 0
@@ -585,6 +589,15 @@
                 yield 'ns%d' % val
         _gen_prefix = _gen_prefix().next
 
+        def _ns_prefix(uri, attr=False):
+            for prefix in chain(('',), namespaces.get(uri, [])):
+                if attr and prefix == '': continue
+                if prefixes.get(prefix, [None])[-1] == uri:
+                    if prefix not in active[-1]:
+                        _push_ns_attr(prefix, uri)
+                    return prefix
+            return None
+        
         for kind, data, pos in stream:
 
             if kind is START or kind is EMPTY:
@@ -593,46 +606,47 @@
                 tagname = tag.localname
                 tagns = tag.namespace
                 if tagns:
-                    if tagns in namespaces:
-                        prefix = namespaces[tagns][-1]
+                    prefix = _ns_prefix(tagns)
+                    if prefix is not None:
                         if prefix:
                             tagname = u'%s:%s' % (prefix, tagname)
                     else:
-                        _push_ns_attr((u'xmlns', tagns))
                         _push_ns('', tagns)
+                        _push_ns_attr('', tagns)
 
                 new_attrs = []
                 for attr, value in attrs:
                     attrname = attr.localname
                     attrns = attr.namespace
                     if attrns:
-                        if attrns not in namespaces:
+                        prefix = _ns_prefix(attrns, attr=True)
+                        if prefix is None:
                             prefix = _gen_prefix()
                             _push_ns(prefix, attrns)
-                            _push_ns_attr(('xmlns:%s' % prefix, attrns))
-                        else:
-                            prefix = namespaces[attrns][-1]
+                            _push_ns_attr(prefix, attrns)
                         if prefix:
                             attrname = u'%s:%s' % (prefix, attrname)
                     new_attrs.append((attrname, value))
 
                 yield kind, (tagname, Attrs(ns_attrs + new_attrs)), pos
                 del ns_attrs[:]
+                active.append(copy.copy(active[-1]))
 
             elif kind is END:
                 tagname = data.localname
                 tagns = data.namespace
                 if tagns:
-                    prefix = namespaces[tagns][-1]
+                    prefix = _ns_prefix(tagns)
                     if prefix:
                         tagname = u'%s:%s' % (prefix, tagname)
                 yield kind, tagname, pos
-
+                active.pop()
+                
             elif kind is START_NS:
                 prefix, uri = data
-                if uri not in namespaces:
-                    prefix = prefixes.get(uri, [prefix])[-1]
-                    _push_ns_attr(_make_ns_attr(prefix, uri))
+                existing = _ns_prefix(uri)
+                if existing is None or (existing == '' and prefix != ''):
+                    _push_ns_attr(prefix, uri)
                 _push_ns(prefix, uri)
 
             elif kind is END_NS:

