Search code examples
pythonxmllxmllxml.objectify

Test the existence of an Element with lxml.objectify


What is the standard way for testing if an element exists or not with lxml.objectify ?

Sample XML :

<?xml version="1.0" encoding="utf-8"?>
<Test>
  <MyElement1>sdfsdfdsfd</MyElement1>
</Test>

Code

from lxml import etree, objectify
with open('config.xml') as f:
    xml = f.read()
root = objectify.fromstring(xml)

print root.MyElement1
print root.MyElement17  # AttributeError: no such child: MyElement17

Then, what is the simplest solution to write something on a specific path ?

root.MyElement1.Blah = 'New'  # this works because MyElement1 already exists
root.MyElement17.Blah = 'New'  # this doesn't work because MyElement17 doesn't exist
root.MyElement1.Foo.Bar = 'Hello' # this doesn't as well... How to do this shortly ?

Solution

  • find method will return None if the element does not exist.

    >>> xml = '''<?xml version="1.0" encoding="utf-8"?>
    ... <Test>
    ...   <MyElement1>sdfsdfdsfd</MyElement1>
    ... </Test>'''
    >>>
    >>> from lxml import objectify
    >>> root = objectify.fromstring(xml)
    >>> root.find('.//MyElement1')
    'sdfsdfdsfd'
    >>> root.find('.//MyElement17')
    >>> root.find('.//MyElement17') is None
    True
    

    UPDATE according to the question edit:

    >>> from lxml import objectify
    >>>
    >>> def add_string(parent, attr, s):
    ...     if len(attr) == 1:
    ...         setattr(parent, attr[0], s)
    ...     else:
    ...         child = getattr(parent, attr[0], None)
    ...         if child is None:
    ...             child = objectify.SubElement(parent, attr[0])
    ...         add_string(child, attr[1:], s)
    ...
    >>> root = objectify.fromstring(xml)
    >>> add_string(root, ['MyElement1', 'Blah'], 'New')
    >>> add_string(root, ['MyElement17', 'Blah'], 'New')
    >>> add_string(root, ['MyElement1', 'Foo', 'Bar'], 'Hello')
    >>>
    >>> root.MyElement1.Blah
    'New'
    >>> root.MyElement17.Blah
    'New'
    >>> root.MyElement1.Foo.Bar
    'Hello'