pythonxmllxmlxml-namespacespodcast

How do I create a namespaced element with lxml?


I'm using lxml to generate an RSS feed that is ultimately used as a podcast. That means I need to add namespaced elements like <itunes:duration> and <itunes:subtitle>. But I'm having so much trouble trying to figure out how to create elements like these with lxml dynamically.

If I simply try:

from lxml import etree

element = etree.Element("itunes:duration")

I get this:

ValueError: Invalid tag name 'itunes:duration'

Next I tried this and got a little closer:

from lxml import etree

etree.register_namespace("itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd")
element = etree.Element("{itunes}duration")
print(etree.tostring(element).decode("utf-8"))

However that resulted in this output:

<ns0:duration xmlns:ns0="itunes"/>

So while that's better than an exception, it's still obviously not right. How can I create an element with an itunes: prefix in the tag name?


Solution

  • Try using etree.QName()...

    from lxml import etree
    
    etree.register_namespace("itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd")
    element = etree.Element(etree.QName("http://www.itunes.com/dtds/podcast-1.0.dtd", "duration"))
    print(etree.tostring(element).decode("utf-8"))
    

    prints...

    <itunes:duration xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"/>
    

    You could also just use Clark notation...

    element = etree.Element("{http://www.itunes.com/dtds/podcast-1.0.dtd}duration")