2

I have a list of child elements from another part of the xml that I am trying to insert as shown here:

import xml.etree.ElementTree as et
import xml

defs_element = xml.etree.ElementTree.Element('ns0:defs')
for pc_def in pc_defs_list:
    et.SubElement(defs_element, 'path', pc_def.attrib)

But when I try I get this error:

TypeError: SubElement() argument 1 must be xml.etree.ElementTree.Element, not Element

Other methods produce similar must be an Element, not Element errors. How do I get this element that is not an element?

Dave Babbitt
  • 1,038
  • 11
  • 20
  • Slimming this down to something I can run, `e=et.Element('foo');et.SubElement(e, 'bar')` works. Can you post something that reproduces the problem? – tdelaney Mar 01 '20 at 00:31
  • Thank you for your patience. When I pull the code out and run it in a Jupyter cell, it works fine. Should I just delete this question? – Dave Babbitt Mar 01 '20 at 23:48
  • That's a good question. If you can still reproduce this in your original environment, we'd have to figure out what's different. If you can get a minimal running program failing in one environment - plus a description of that environment - then its worth keeping. If its just not reproducable by anybody out here, its less useful. – tdelaney Mar 02 '20 at 00:51

2 Answers2

1

There are two possible problems:

  1. Does the problem go away if you remove the namespace ns0: prefix? Creating a namespaced element in ElementTree is not as simple as just prefixing with the prefix. See the top answers in Emitting namespace specifications with ElementTree in Python to show how namespace might work:
et.register_namespace('ns0',"http://ns0.namespaces.org")
defs_element = xml.etree.ElementTree.Element('{http://ns0.namespaces.org}:defs')
  1. You're not explaining where pc_defs_list comes from. Is it possibly loaded in another file? ElementTree in its C version is very picky about the exact class that is being passed in. So that if the elements come from a file loading the python version of ElementTree, you can't insert them in your ElementTree. Even if they're both loading the C-version of ElementTree (cElementTree before Python 3.3), if they're not loading from the same binary file (one is inside the virtual environment, one is outside, for instance), then this message appears (formerly the even more cryptic argument 1 must be Element, not Element message). This seems less likely to be the case here because you're creating a new SubElement rather than appending an existing element directly.

In a Django environment once, I even had problems with:

import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element

root = Element('root')
hi = ET.Element('hi')
root.append(hi)

with a complaint that they were incompatible objects

0

Something like this works:

defs_xml_str = '<defs>'
for path_str in path_strs_list:
    defs_xml_str += path_str
defs_xml_str += '</defs>'
legend_1_xml.insert(0, et.fromstring(defs_xml_str))
Dave Babbitt
  • 1,038
  • 11
  • 20