3

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?

Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
soapergem
  • 9,263
  • 18
  • 96
  • 152
  • 1
    Did you try reading the lxml tutorial section about namespaces https://lxml.de/tutorial.html#namespaces - you can probably find many other sources of information on this topic by using a popular search engine with the search for: __lxml namespace__ – DisappointedByUnaccountableMod Jun 15 '20 at 19:49
  • @barny Yup and I couldn't make two cents of it. I was hoping someone had already done this and could provide a more concise code snippet. – soapergem Jun 15 '20 at 19:50

1 Answers1

7

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")
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
  • This is great! Do you also happen to know if there's any way to strip the `xmlns:itunes` attribute from that? – soapergem Jun 15 '20 at 20:13
  • @soapergem - No, I don't think so. If you strip it it's no longer [namespace well formed](https://stackoverflow.com/a/25830482/317052). However, once you start combining elements to create your document the namespace declaration should only appear once when you serialize it. – Daniel Haley Jun 15 '20 at 20:16