Emitting namespace specifications with ElementTree in Python

强颜欢笑 提交于 2019-11-27 00:28:19

问题


I am trying to emit an XML file with element-tree that contains an XML declaration and namespaces. Here is my sample code:

from xml.etree import ElementTree as ET
ET.register_namespace('com',"http://www.company.com") #some name

# build a tree structure
root = ET.Element("STUFF")
body = ET.SubElement(root, "MORE_STUFF")
body.text = "STUFF EVERYWHERE!"

# wrap it in an ElementTree instance, and save as XML
tree = ET.ElementTree(root)

tree.write("page.xml",
           xml_declaration=True,
           method="xml" )

However, neither the <?xml tag comes out nor any namespace/prefix information. I'm more than a little confused here.


回答1:


Although the docs say otherwise, I only was able to get an <?xml> declaration by specifying both the xml_declaration and the encoding.

You have to declare nodes in the namespace you've registered to get the namespace on the nodes in the file. Here's a fixed version of your code:

from xml.etree import ElementTree as ET
ET.register_namespace('com',"http://www.company.com") #some name

# build a tree structure
root = ET.Element("{http://www.company.com}STUFF")
body = ET.SubElement(root, "{http://www.company.com}MORE_STUFF")
body.text = "STUFF EVERYWHERE!"

# wrap it in an ElementTree instance, and save as XML
tree = ET.ElementTree(root)

tree.write("page.xml",
           xml_declaration=True,encoding='utf-8',
           method="xml")

Output (page.xml)

<?xml version='1.0' encoding='utf-8'?><com:STUFF xmlns:com="http://www.company.com"><com:MORE_STUFF>STUFF EVERYWHERE!</com:MORE_STUFF></com:STUFF>

ElementTree doesn't pretty-print either. Here's pretty-printed output:

<?xml version='1.0' encoding='utf-8'?>
<com:STUFF xmlns:com="http://www.company.com">
    <com:MORE_STUFF>STUFF EVERYWHERE!</com:MORE_STUFF>
</com:STUFF>

You can also declare a default namespace and don't need to register one:

from xml.etree import ElementTree as ET

# build a tree structure
root = ET.Element("{http://www.company.com}STUFF")
body = ET.SubElement(root, "{http://www.company.com}MORE_STUFF")
body.text = "STUFF EVERYWHERE!"

# wrap it in an ElementTree instance, and save as XML
tree = ET.ElementTree(root)

tree.write("page.xml",
           xml_declaration=True,encoding='utf-8',
           method="xml",default_namespace='http://www.company.com')

Output (pretty-print spacing is mine)

<?xml version='1.0' encoding='utf-8'?>
<STUFF xmlns="http://www.company.com">
    <MORE_STUFF>STUFF EVERYWHERE!</MORE_STUFF>
</STUFF>



回答2:


I've never been able to get the <?xml tag out of the element tree libraries programatically so I'd suggest you try something like this.

from xml.etree import ElementTree as ET
root = ET.Element("STUFF")
root.set('com','http://www.company.com')
body = ET.SubElement(root, "MORE_STUFF")
body.text = "STUFF EVERYWHERE!"

f = open('page.xml', 'w')
f.write('<?xml version="1.0" encoding="UTF-8"?>' + ET.tostring(root))
f.close()

Non std lib python ElementTree implementations may have different ways to specify namespaces, so if you decide to move to lxml, the way you declare those will be different.



来源:https://stackoverflow.com/questions/4997848/emitting-namespace-specifications-with-elementtree-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!