mirror of
https://github.com/correl/SleekXMPP.git
synced 2024-11-24 03:00:15 +00:00
Updated ElementBase._delSub and added unit tests.
_delSub can now accept a path and will optionally remove any empty parent elements after deleting the target elements.
This commit is contained in:
parent
2fa58a74ab
commit
5d458bf6c2
2 changed files with 114 additions and 7 deletions
|
@ -417,6 +417,44 @@ class ElementBase(object):
|
||||||
element.text = text
|
element.text = text
|
||||||
return element
|
return element
|
||||||
|
|
||||||
|
def _delSub(self, name, all=False):
|
||||||
|
"""
|
||||||
|
Remove sub elements that match the given name or XPath.
|
||||||
|
|
||||||
|
If the element is in a path, then any parent elements that become
|
||||||
|
empty after deleting the element may also be deleted if requested
|
||||||
|
by setting all=True.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name -- The name or XPath expression for the element(s) to remove.
|
||||||
|
all -- If True, remove all empty elements in the path to the
|
||||||
|
deleted element. Defaults to False.
|
||||||
|
"""
|
||||||
|
name = self._fix_ns(name)
|
||||||
|
path = name.split("/")
|
||||||
|
original_target = path[-1]
|
||||||
|
|
||||||
|
for level, _ in enumerate(path):
|
||||||
|
# Generate the paths to the target elements and their parent.
|
||||||
|
element_path = "/".join(path[:len(path) - level])
|
||||||
|
parent_path = "/".join(path[:len(path) - level - 1])
|
||||||
|
|
||||||
|
elements = self.xml.findall(element_path)
|
||||||
|
parent = self.xml.find(parent_path)
|
||||||
|
|
||||||
|
if elements:
|
||||||
|
if parent is None:
|
||||||
|
parent = self.xml
|
||||||
|
for element in elements:
|
||||||
|
if element.tag == original_target or not element.getchildren():
|
||||||
|
# Only delete the originally requested elements, and any
|
||||||
|
# parent elements that have become empty.
|
||||||
|
parent.remove(element)
|
||||||
|
if not all:
|
||||||
|
# If we don't want to delete elements up the tree, stop
|
||||||
|
# after deleting the first level of elements.
|
||||||
|
return
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def attrib(self): #backwards compatibility
|
def attrib(self): #backwards compatibility
|
||||||
return self
|
return self
|
||||||
|
@ -512,13 +550,6 @@ class ElementBase(object):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _delSub(self, name):
|
|
||||||
if '}' not in name:
|
|
||||||
name = "{%s}%s" % (self.namespace, name)
|
|
||||||
for child in self.xml.getchildren():
|
|
||||||
if child.tag == name:
|
|
||||||
self.xml.remove(child)
|
|
||||||
|
|
||||||
def appendxml(self, xml):
|
def appendxml(self, xml):
|
||||||
self.xml.append(xml)
|
self.xml.append(xml)
|
||||||
return self
|
return self
|
||||||
|
|
|
@ -352,5 +352,81 @@ class TestElementBase(SleekTest):
|
||||||
</foo>
|
</foo>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
def testDelSub(self):
|
||||||
|
"""Test removing sub elements."""
|
||||||
|
|
||||||
|
class TestStanza(ElementBase):
|
||||||
|
name = "foo"
|
||||||
|
namespace = "foo"
|
||||||
|
interfaces = set(('bar', 'baz'))
|
||||||
|
|
||||||
|
def setBar(self, value):
|
||||||
|
self._setSubText("path/to/only/bar", value);
|
||||||
|
|
||||||
|
def getBar(self):
|
||||||
|
return self._getSubText("path/to/only/bar")
|
||||||
|
|
||||||
|
def delBar(self):
|
||||||
|
self._delSub("path/to/only/bar")
|
||||||
|
|
||||||
|
def setBaz(self, value):
|
||||||
|
self._setSubText("path/to/just/baz", value);
|
||||||
|
|
||||||
|
def getBaz(self):
|
||||||
|
return self._getSubText("path/to/just/baz")
|
||||||
|
|
||||||
|
def delBaz(self):
|
||||||
|
self._delSub("path/to/just/baz")
|
||||||
|
|
||||||
|
stanza = TestStanza()
|
||||||
|
stanza['bar'] = 'a'
|
||||||
|
stanza['baz'] = 'b'
|
||||||
|
|
||||||
|
self.checkStanza(TestStanza, stanza, """
|
||||||
|
<foo xmlns="foo">
|
||||||
|
<path>
|
||||||
|
<to>
|
||||||
|
<only>
|
||||||
|
<bar>a</bar>
|
||||||
|
</only>
|
||||||
|
<just>
|
||||||
|
<baz>b</baz>
|
||||||
|
</just>
|
||||||
|
</to>
|
||||||
|
</path>
|
||||||
|
</foo>
|
||||||
|
""")
|
||||||
|
|
||||||
|
del stanza['bar']
|
||||||
|
del stanza['baz']
|
||||||
|
|
||||||
|
self.checkStanza(TestStanza, stanza, """
|
||||||
|
<foo xmlns="foo">
|
||||||
|
<path>
|
||||||
|
<to>
|
||||||
|
<only />
|
||||||
|
<just />
|
||||||
|
</to>
|
||||||
|
</path>
|
||||||
|
</foo>
|
||||||
|
""", use_values=False)
|
||||||
|
|
||||||
|
stanza['bar'] = 'a'
|
||||||
|
stanza['baz'] = 'b'
|
||||||
|
|
||||||
|
stanza._delSub('path/to/only/bar', all=True)
|
||||||
|
|
||||||
|
self.checkStanza(TestStanza, stanza, """
|
||||||
|
<foo xmlns="foo">
|
||||||
|
<path>
|
||||||
|
<to>
|
||||||
|
<just>
|
||||||
|
<baz>b</baz>
|
||||||
|
</just>
|
||||||
|
</to>
|
||||||
|
</path>
|
||||||
|
</foo>
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestElementBase)
|
suite = unittest.TestLoader().loadTestsFromTestCase(TestElementBase)
|
||||||
|
|
Loading…
Reference in a new issue