5

I'm trying to create an XML file so that it has the following skeleton, preferably using the xml.etree modules in Python 2.7:

<?xml version="1.0"?>
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" thing1="this" thing2="that">
  ....
  <somedata bar="1">
    <moredata whatsit="42"></moredata>
  </somedata>
  ....
</foo>

It's the "foo ...." line that vexes me. I tried using nsmap for bringing in xsi and xsd, but that led to a "cannot serialize" error.

I could construct or otherwise hack that line's text to be exactly as I want it, but I'd like to learn to do this programmatically using xml.etree (pulling in an external library is not preferable in this situation).

I'd think this is a common pattern but I'm just not finding it anywhere for Python and etree.

2
  • I tried to do something similar once, unfortunately it seems xml.etree is too weak for that. Commented Jun 13, 2013 at 10:10
  • Is it possible that all that "xmlns:xsi" and "xmlns:xsd" business is simply superfluous, since "thing1" and "thing2" do not have any namespace attached to them anyway? I'm just worried that I'd be oversimplifying this for one case and missing a chance to learn to do it properly (other cases might have more stringent requirements). Commented Jun 13, 2013 at 10:34

2 Answers 2

6

If the prefixes are used in the document; you could call register_namespace() to add them:

import sys
import xml.etree.ElementTree as etree

xsi =  "http://www.w3.org/2001/XMLSchema-instance"
xsd =  "http://www.w3.org/2001/XMLSchema"
ns = {"xmlns:xsi": xsi, "xmlns:xsd": xsd}
for attr, uri in ns.items():
    etree.register_namespace(attr.split(":")[1], uri)

foo = etree.Element("foo",
    dict(thing1="this", thing2="that")) # put `**ns))` if xsi, xsd are unused
somedata = etree.SubElement(foo, "somedata", dict(bar="1"))
etree.SubElement(somedata, "moredata",
    {"whatsit": "42", etree.QName(xsi, "type"): etree.QName(xsd, "string")})

etree.ElementTree(foo).write(sys.stdout, xml_declaration=True)

Otherwise, you could set the attributes explicitly (ns dict) if you need it.

Sign up to request clarification or add additional context in comments.

1 Comment

That seems to work (I'm not quite sure I need the "xsi:type="xsd:string"" bit in the moredata output, but at least this shows how to get the namespaces set correctly). Thank you! Upvote in kind if you think my question and your answer would help others (I think it would).
2
import xml.etree.ElementTree as et

foo = et.Element('foo', **{'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'}, **{'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema'})
somedata = et.SubElement(foo, 'somedata', bar='1')
moredata = et.SubElement(somedata, 'moredata', whatsit='42')
tree = et.ElementTree(foo)
tree.write('file.xml')

1 Comment

While this code snippet may be the solution, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.