GorillaPatch
GorillaPatch

Reputation: 5057

Generate XML Document in Python 3 using Namespaces and ElementTree

I am having problems generating a XML document using the ElementTree framework in Python 3. I tried registering the namespace before setting up the document. Right now it seems that I can generate a XML document only by adding the namespace to each element like a=Element("{full_namespace_URI}element_name") which seems tedious.

How do I setup the default namespace and can omit putting it in each element?

Any help is appreciated.

I have written a small demo program for Python 3:

    from io import BytesIO                                                                                                                                                
    from xml.etree import ElementTree as ET                                                                                                                               
                                                                                                                                                                          
    ET.register_namespace("", "urn:dslforum-org:service-1-0")                                                                                                             
                                                                                                                                                                          
    """                                                                                                                                                                   
    desired output                                                                                                                                                        
    ==============                                                                                                                                                        
    <?xml version='1.0' encoding='utf-8'?>                                                                                                                                
    <topNode xmlns="urn:dslforum-org:service-1-0"">                                                                                                                       
        <childNode>content</childNode>                                                                                                                                    
    </topNode>                                                                                                                                                            
    """                                                                                                                                                                   
                                                                                                                                                                          
                                                                                                                                                                          
    # build XML document without namespaces                                                                                                                               
    a = ET.Element("topNode")                                                                                                                                             
    b = ET.Element("childNode")                                                                                                                                           
    b.text = "content"                                                                                                                                                    
    a.append(b)                                                                                                                                                           
    tree = ET.ElementTree(a)                                                                                                                                              
                                                                                                                                                                          
    # build XML document with namespaces                                                                                                                                  
    a_ns = ET.Element("{dsl}topNode")                                                                                                                                     
    b_ns = ET.Element("{dsl}childNode")                                                                                                                                   
    b_ns.text = "content"                                                                                                                                                 
    a_ns.append(b_ns)                                                                                                                                                     
    tree_ns = ET.ElementTree(a_ns)                                                                                                                                        
                                                                                                                                                                          
    def print_element_tree(element_tree, comment, default_namespace=None):                                                                                                
        """                                                                                                                                                               
        print element tree with comment to standard out                                                                                                                   
        """                                                                                                                                                               
        with BytesIO() as buf:                                                                                                                                            
            element_tree.write(buf, encoding="utf-8", xml_declaration=True,                                                                                               
                               default_namespace=default_namespace)                                                                                                       
            buf.seek(0)                                                                                                                                                   
            print(comment)                                                                                                                                                
            print(buf.read().decode("utf-8"))                                                                                                                             
                                                                                                                                                                          
    print_element_tree(tree, "Element Tree without XML namespace")                                                                                                        
    print_element_tree(tree_ns, "Element Tree with XML namespace", "dsl")

Upvotes: 0

Views: 1808

Answers (1)

Mike Organek
Mike Organek

Reputation: 12484

I believe you are overthinking this.

Registering a default namespace in your code avoids the ns0: aliases.

Registering any namespaces you will use while creating a document allows you to designate the alias used for each namespace.

To achieve your desired output, assign the namespace to your top element:

a = ET.Element("{urn:dslforum-org:service-1-0}topNode")

The preceding ET.register_namespace("", "urn:dslforum-org:service-1-0") will make that the default namespace in the document, assign it to topNode, and not prefix your tag names.

<?xml version='1.0' encoding='utf-8'?>
<topNode xmlns="urn:dslforum-org:service-1-0"><childNode>content</childNode></topNode>

If you remove the register_namespace() call, then you get this monstrosity:

<?xml version='1.0' encoding='utf-8'?>
<ns0:topNode xmlns:ns0="urn:dslforum-org:service-1-0"><childNode>content</childNode></ns0:topNode>

Upvotes: 2

Related Questions