Namespacing inside tags with Python lxml's SubElement
Question: I'm using Python and the lxml library to produce an XML file that I want to
look like this:

    
    
    <item>
      <a:text>hello</a:text>
    </item>
    

However, I can't manage to produce this, I've tried the following code:

    
    
    import lxml.etree as etree
    item = etree.Element('item')
    el = etree.SubElement(item, 'text', nsmap={'a': 'http://example.com/')
    

But then I end up with:

    
    
    <item>
      <text xmlns="http://example.com/">hello</text>
    </item>
    

I also tried this after some inspiration from the lxml namespaces
documentation (<http://lxml.de/tutorial.html#namespaces>):

    
    
    import lxml.etree as etree
    item = etree.Element('item')
    el = etree.SubElement(item, '{a}text')
    

But that gives me:

    
    
    <item>
      <ns1:text xmlns:ns1="a">hello</text>
    </item>
    

Is there any way to get the XML format I need with lxml ?


Answer: The first thing to note is that this...

    
    
    <item>
      <a:text>hello</a:text>
    </item>
    

...is not valid XML. `a:` is a namespace _prefix_ , but somewhere you have to
map it to an actual namespace, as in:

    
    
    <item xmlns:a="http://example.com/">
      <a:text>hello</a:text>
    </item>
    

As you read in the lxml documentation, you can use the `{namespace}element`
syntax to specify a namespace...but this uses an actual namespace, _not_ a
namespace prefix (which is why your second example did not work as expected).

You can get what I think you want like this:

    
    
    >>> from lxml import etree
    >>> item = etree.Element('item', nsmap={'a': 'http://example.com/'})
    >>> e1 = etree.SubElement(item, '{http://example.com/}text')
    

Which gives you:

    
    
    >>> print etree.tostring(item, pretty_print=True)
    <item xmlns:a="http://example.com/">
      <a:text/>
    </item>
    

It's also worth noting that from the perspective of XML, the above is
_exactly_ equivalent to:

    
    
    <item>
      <text xmlns="http://example.com/">hello</text>
    </item>
    

