Поскольку это звучит как решение, может быть, не в поле зрения ...
Пока не будет найдено лучшее решение, вот хакерский обходной путь для следующей бедной души ...
def xml_fixup(s): # give it the XML as a tring
flags = re.DOTALL
pat_quotes = '\"[^\"]*\"|\'[^\']*\''
re_quotes = re.compile('(%s)([^>\\s])' % pat_quotes, flags) # TODO: cache
re_pieces = re.compile('([^<]+)|(<)((?:[^\"\'>]+|%s)*)(>)' % pat_quotes, flags) # TODO: cache
pieces = re_pieces.findall(s)
return s[:0].join(map(lambda m: m[0] or m[1] + re_quotes.sub('\\1 \\2', m[2]) + m[3], pieces))
print(xml_fixup('<foo bar=""baz=""></foo>')) # <foo bar="" baz=""></foo>
Очки Брауни, если вы обнаружите ошибки в этом!