+class XmlNode:
+ def __init__(self, node, namespaces):
+ self.node = node
+ self.namespaces = namespaces
+ self.attrib = node.attrib
+
+ def xpath(self, xpath, namespaces=None):
+ if not namespaces:
+ namespaces = self.namespaces
+ return self.node.xpath(xpath, namespaces=namespaces)
+
+ def add_element(name, *args, **kwds):
+ element = etree.SubElement(name, args, kwds)
+ return XmlNode(element, self.namespaces)
+
+ def remove_elements(name):
+ """
+ Removes all occurences of an element from the tree. Start at
+ specified root_node if specified, otherwise start at tree's root.
+ """
+
+ if not element_name.startswith('//'):
+ element_name = '//' + element_name
+ elements = self.node.xpath('%s ' % name, namespaces=self.namespaces)
+ for element in elements:
+ parent = element.getparent()
+ parent.remove(element)
+
+ def set(self, key, value):
+ self.node.set(key, value)
+
+ def set_text(self, text):
+ self.node.text = text
+
+ def unset(self, key):
+ del self.node.attrib[key]
+
+ def toxml(self):
+ return etree.tostring(self.node, encoding='UTF-8', pretty_print=True)
+
+ def __str__(self):
+ return self.toxml()
+