Как генерировать XML-документы с пространствами имен в Python

Я пытаюсь создать XML-документ с пространствами имен, в настоящее время с Python 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())

Пространство имен сохраняется (doc.childNodes[0].namespaceURI равно 'http://example.net/ns'), но почему оно отсутствует в выводе?

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

Я жду:

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

or

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

person phihag    schedule 14.05.2009    source источник


Ответы (2)


createElementNS() определяется как:

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())

дает:

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

…не совсем там…

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())

дает:

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

альтернативно:

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())

который производит:

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

Похоже, вам придется делать это вручную. Element.writexml() не показывает никаких указаний на то, что пространства имен получат какую-либо особую обработку.

РЕДАКТИРОВАТЬ: этот ответ предназначен только для xml.dom.minidom, поскольку ОП использовал его в вопросе. Я не указываю, что в Python вообще нельзя было использовать пространства имен XML. ;-)

person Tomalak    schedule 14.05.2009
comment
Это работает, но это настоящий хак. Я не могу вспомнить ни одной другой реализации DOM с поддержкой пространства имен, которая на самом деле не поддерживает пространства имен. Надеюсь, для Python тоже есть. - person phihag; 14.05.2009
comment
Я искал исходный код для minidom, и похоже, что этот хак самый близкий, который вы можете получить. Выходная поддержка пространств имен в minidom практически отсутствует (AFAICS), они не получают специальной обработки. Однако они анализируются правильно, поэтому, когда они были во входной строке, они также будут и в выходных данных. В остальном minidom рассматривает их как обычные атрибуты и элементы с забавными названиями. - person Tomalak; 14.05.2009

Эта функция уже предложена; патч дремал в базе данных ошибок Python. См. ответ Томалака (вкратце: вручную добавьте атрибут xmlns) для обходного пути.

person phihag    schedule 14.05.2009