Remove a node or attribute.  For multipart XPaths that are
    constructible by :mod:`eulxml.xmlmap`, the corresponding nodes
    will be removed if they are empty (other than predicates specified
    in the XPath).

    :param xast: parsed xpath (xpath abstract syntax tree) from
	:mod:`eulxml.xpath`
    :param node: lxml node relative to which xast should be removed
    :param context: any context required for the xpath (e.g.,
    	namespace definitions)
    :param if_empty: optional boolean; only remove a node if it is
	empty (no attributes and no child nodes); defaults to False

    :returns: True if something was deleted

def _remove_xml(xast, node, context, if_empty=False):
    '''Remove a node or attribute.  For multipart XPaths that are
    constructible by :mod:`eulxml.xmlmap`, the corresponding nodes
    will be removed if they are empty (other than predicates specified
    in the XPath).

    :param xast: parsed xpath (xpath abstract syntax tree) from
	:mod:`eulxml.xpath`
    :param node: lxml node relative to which xast should be removed
    :param context: any context required for the xpath (e.g.,
    	namespace definitions)
    :param if_empty: optional boolean; only remove a node if it is
	empty (no attributes and no child nodes); defaults to False

    :returns: True if something was deleted
    '''
    if isinstance(xast, ast.Step):
        if isinstance(xast.node_test, ast.NameTest):
            if xast.axis in (None, 'child'):
                return _remove_child_node(node, context, xast, if_empty=if_empty)
            elif xast.axis in ('@', 'attribute'):
                return _remove_attribute_node(node, context, xast)
        # special case for text()
        # since it can't be removed, at least clear out any value in the text node
        elif _is_text_nodetest(xast):
            node.text = ''
            return True

    # If the xpath is a multi-step path (e.g., foo[@id="a"]/bar[@id="b"]/baz),
    # remove the leaf node.  If the remaining portions of that path
    # could have been constructed when setting the node and are empty
    # (other than any predicates defined in the xpath), remove them as well.
    elif isinstance(xast, ast.BinaryExpression):
        if xast.op == '/':
            left_xpath = serialize(xast.left)
            left_node = _find_xml_node(left_xpath, node, context)
            if left_node is not None:
                # remove the last element in the xpath
                removed = _remove_xml(xast.right, left_node, context,
                                      if_empty=if_empty) # honor current if_empty flag

                # If the left portion of the xpath is something we
                # could have constructed, remove it if it is empty.
                if removed and _predicate_is_constructible(left_xpath):
                    _remove_xml(xast.left, node, context, if_empty=True)

                # report on whether the leaf node was removed or not,
                # regardless of what was done with left portion of the path
                return removed

    return False