'Set the text contents of a sub element.
In case the element does not exist, a element will be created,
and its text contents will be set.
If the text is set to an empty string, or None, then the
element will be removed, unless keep is set to True.
:param name: The name or XPath expression of the element.
:param text: The new textual content of the element. If the text
is an empty string or None, the element will be removed
unless the parameter keep is True.
:param keep: Indicates if the element should be kept if its text is
removed. Defaults to False.'

def _set_sub_text(self, name, text=None, keep=False, lang=None):

    default_lang = self.get_lang()
    if (lang is None):
        lang = default_lang
    if ((not text) and (not keep)):
        return self._del_sub(name, lang=lang)
    path = self._fix_ns(name, split=True)
    name = path[(-1)]
    parent = self.xml
    missing_path = []
    search_order = path[:(-1)]
    while search_order:
        parent = self.xml.find(u'/'.join(search_order))
        ename = search_order.pop()
        if (parent is not None):
            break
        else:
            missing_path.append(ename)
    missing_path.reverse()
    if (parent is not None):
        elements = self.xml.findall(u'/'.join(path))
    else:
        parent = self.xml
        elements = []
    for ename in missing_path:
        element = ET.Element(ename)
        parent.append(element)
        parent = element
    for element in elements:
        elang = element.attrib.get((u'{%s}lang' % XML_NS), default_lang)
        if (((not lang) and (elang == default_lang)) or (lang and (lang == elang))):
            element.text = text
            return element
    element = ET.Element(name)
    element.text = text
    if (lang and (lang != default_lang)):
        element.attrib[(u'{%s}lang' % XML_NS)] = lang
    parent.append(element)
    return element
