views:

1228

answers:

2

I'm trying to generate an XML document with namespaces, currently with Python's xml.dom.minidom:

import xml.dom.minidom
doc = xml.dom.minidom.Document()
el = doc.createElementNS('http://example.net/ns', 'el')
doc.appendChild(el)
print(doc.toprettyxml())

The namespace is saved (doc.childNodes[0].namespaceURI is 'http://example.net/ns'), but why is it missing in the output?

<?xml version="1.0" ?>
<el/>

I expect:

<?xml version="1.0" ?>
<el xmlns="http://example.net/ns" />

or

<?xml version="1.0" ?>
<randomid:el xmlns:randomid="http://example.net/ns" />
+4  A: 

createElementNS() is defined as:

def createElementNS(self, namespaceURI, qualifiedName):
    prefix, localName = _nssplit(qualifiedName)
    e = Element(qualifiedName, namespaceURI, prefix)
    e.ownerDocument = self
    return e

so...

import xml.dom.minidom
doc = xml.dom.minidom.Document()
el = doc.createElementNS('http://example.net/ns', 'ex:el')
#--------------------------------------------------^^^^^
doc.appendChild(el)
print(doc.toprettyxml())

yields:

<?xml version="1.0" ?>
<ex:el/>

...not quite there...

import xml.dom.minidom
doc = xml.dom.minidom.Document()
el = doc.createElementNS('http://example.net/ns', 'ex:el')
el.setAttribute("xmlns:ex", "http://example.net/ns")
doc.appendChild(el)
print(doc.toprettyxml())

yields:

<?xml version="1.0" ?>
<ex:el xmlns:ex="http://example.net/ns"/&gt;

alternatively:

import xml.dom.minidom
doc = xml.dom.minidom.Document()
el = doc.createElementNS('http://example.net/ns', 'el')
el.setAttribute("xmlns", "http://example.net/ns")
doc.appendChild(el)
print(doc.toprettyxml())

wich produces:

<?xml version="1.0" ?>
<el xmlns="http://example.net/ns"/&gt;

It looks like you'd have to do it manually. Element.writexml() shows no indication that namespaces would get any special treatment.

EDIT: This answer is targeted at xml.dom.minidom only, since the OP used it in the question. I do not indicate that it was impossible to use XML namespaces in Python generally. ;-)

Tomalak
This works, but it's quite a hack. I can't remember any other namespace-aware DOM implementation that does not really support namespaces. I hope there is one for Python, too.
phihag
I was looking a the source code for minidom, and it looks like this hack is the closest you can get. The "output" support for namespaces in minidom is virtually non-existent (AFAICS), they receive no special treatment. However they are parsed correctly, so when they were in the input string, they're gonna be in the output as well. Other than that minidom treats them as normal attributes and elements with funny names.
Tomalak
+1  A: 

This feature is already proposed; a patch is slumbering in the Python bug database. See Tomalak's answer (in short: Manually add the xmlns attribute) for a workaround.

phihag